Friday, January 29, 2010

JSR 303 Bean Validation: @ValidateDateRange - A reusable constraint annotation to validate date ranges

In a previous blog-post, I have described my experience on JSR 303 Bean Validation, and in the process, this @ValidateDateRange constraint annotation came upon into my mind. I thought that it would be useful so it inspired me to create its implementation and eventually made this blog-post.

The @ValidateDateRange is a class-level constraint annotation that will validate a date range represented by two java.util.Date properties of an object. This can be reused in any class.
@ValidateDateRange(start="startDate", end="endDate")
public class MyEntity {
   private Date startDate;
   private Date endDate;
   ...
}

The annotation definition are as follows:
package blogspot.soadev.validator;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import java.util.Date;

import javax.validation.Constraint;
import javax.validation.ConstraintPayload;

@Target( { TYPE, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = {DateRangeValidator.class} )
@Documented

public @interface ValidateDateRange {
    String message() default "{end} should be later than {start}";
    String start();
    String end();
    Class[] groups() default {};
    Class[] payload() default {};       
}
And the implementing DateRangeValidator are as follows:
package blogspot.soadev.validator;

import java.lang.reflect.Field;
import java.util.Date;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class DateRangeValidator implements ConstraintValidator{
    private String start;
    private String end;
    
    public void initialize(ValidateDateRange validateDateRange) {
        start = validateDateRange.start();
        end =  validateDateRange.end();
    }

    public boolean isValid(Object object,
                           ConstraintValidatorContext constraintValidatorContext) {
        try {
            Class clazz = object.getClass();
            Date startDate = null;
            Method startGetter = clazz.getMethod(getAccessorMethodName(start), new Class[0]);
            Object startGetterResult = startGetter.invoke(object, null);
            if (startGetterResult != null && startGetterResult instanceof Date){
                startDate = (Date) startGetterResult;
            }else{
                return false;
            }
            Date endDate = null;
            Method endGetter = clazz.getMethod(getAccessorMethodName(end), new Class[0]);
            Object endGetterResult = endGetter.invoke(object, null);
            if (endGetterResult == null){
                return true;
            }
            if (endGetterResult instanceof Date){
                endDate = (Date) endGetterResult;
            }
            return (startDate.before(endDate));           
        } catch (Throwable e) {
            System.err.println(e);
        }

        return false;
    }
    private String getAccessorMethodName(String property){
        StringBuilder builder = new StringBuilder("get");
        builder.append(Character.toUpperCase(property.charAt(0))); 
        builder.append(property.substring(1));
        return builder.toString();
    }
}

Related Posts


Cheers!

Thursday, January 28, 2010

Oracle XE: Exporting and Importing Dump Files

An easy way to copy a schema would be through JDeveloper Database Copy Utility under Tools>Database>Database Copy... menu. But in our case, we encounter errors in the transfer of records from the source to my target connection and many of the records were not exported successfully. This is the reason why we resorted to exporting and importing dump files.

Yesterday, I was given a dump file which was generated from one of my colleague's machine. Since I am new to this import and export thing and I was not involved in the export process when the file was generated, I face the challenge on how to successfully import the dump file to my Oracle XE.

I do my research on the internet but I was overwhelmed with too much information (information overload), and in applying the crowded information that I have gathered, I encountered a bunch of errors some of which are listed below:
Error 1:
ORA-39001: invalid argument value
ORA-39000: bad dump file specification
ORA-39143: dump file "my_sample_dumpfile.dmp" may be an original export dump file
Reason: I used impdp instead of imp command.

Error 2:
IMP-00002:failed to open expdat.dmp for read
Import File:EXPDAT.DMP>
Reason: I did not specify a full file path.

Error 3:
IMP-00013: only a DBA can import a file exported by another DBA
Reason: I did not specify '... as sysdba'

But finally, I was able to make it. How? Please see the steps below:
1) I created my target user using the Oracle XE browser base UI (Go To Database Home Page)
2) I run the following command in windows command prompt:
imp 'targetUser/password as sysdba' file=C:/my_sample_dumpfile.dmp fromuser=userWhoExported touser=targetUser
what to expect as result would be something like this:
.importing USERWHOEXPORTED's object to TARGETUSER
importing table ...
importing table ...
About to enable constraints...
Import terminated successfully without warnings.

If you want to know the parameters of the imp command, type:
imp help=y

Now that I realized how easy it is to import a dump file, I became excited on how to do the exporting, and indeed, it was even easier. To generate a dump file, open your command prompt and enter something like the following:
exp username/password file=C:/exported_file.dmp owner=yourschema
yourschema is the user/schema that you wanted to export which can be the same with username value.

Cheers!

Tuesday, January 26, 2010

JSR 303 Bean Validation: @AssertMethodAsTrue - A reusable constraint annotation that spans multiple properties.

I have made my own hands-on on this Bean Validation based on the [hibernate-validator-4.0.0.Beta2] and the experience was great. One thing that I have observed though is that there is no built-in annotation to check for a constraint spanning multiple properties, or to check if a certain property is valid based on other properties. One obvious example to this is validating date ranges where you would usually have two properties like startDate and endDate where it doesn't make sense to have a startDate property that is later than the endDate. You could say - why not create a new class-level constraint and
apply it like below:
@ValidateDateRange(start="startDate", end="endDate")
public class MyEntity {
   private Date startDate;
   private Date endDate;
   ...
}
Well, this is good because it is likely that I can reuse this constraint in other entities needing validation on date ranges (I just realized in writing this that it also interesting to post a blog on an implementation of the @ValidateDateRange annotation above). The following are some of the annotations which are reusable to other entities.
  • @NotNull
  • @NotEmpty
  • @Size
  • @Min
  • @Max
  • @DecimalMin
  • @DecimalMax
  • @Email
  • @Pattern
But how about other validation spanning multiple properties that is not likely to be reused in other entities (just like the sample class-level constraint @ValidPassengerCount in the Bean Validator documentation)? I believe, that to create two additional classes to support such simple validation requirement of an specific entity is too much work especially that it is most likely that in addition to checking if the number of passengers is valid , you will also have two or more other validation requirements on the same entity. For example, if I have three business logic for an entity to be validated, it means creating more or less six additional classes to support the three constraint validation. The sad thing is, I cannot reuse such custom constraint validations to other entities.

The Bean Validation reference implementation has @AssertTrue annotation which can be applied to a property or getter method, but an exception is raised if you will try to access other properties value inside a getter method.

So how then could we easily validate a business logic constraint that spans multiple properties without too much work? Our answer is the reusable @AssertMethodAsTrue class-level constraint annotation that accepts a method name as a parameter. The method name that you set as parameter should return a boolean value. An example would be:
@AssertMethodAsTrue(value="isPassengerCountValid", message="Invalid passenger count!")
public class Car {
    @Min(2)
    private int seatCount;
    @NotNull
    List passengers;

    public boolean isPassengerCountValid(){
        if(this.seatCount >= passengers.size()){
        return true;
        }
        return false;
    }
}
The definition of the @AssertMethodAsTrue annotation are as follows:
package blogspot.soadev.validator;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.ConstraintPayload;

@Target( { TYPE, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = {AssertMethodAsTrueValidator.class} )
@Documented

public @interface AssertMethodAsTrue {
    String message() default "{value} returned false";
    String value() default "isValid";
    Class[] groups() default {};
    Class[] payload() default {};       
}

And the corresponding implementing validator class that use reflection:
package blogspot.soadev.validator;

import java.lang.reflect.Method;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class AssertMethodAsTrueValidator implements ConstraintValidator{    
    private String methodName;
    
    public void initialize(AssertMethodAsTrue assertMethodAsTrue) {
        methodName =  assertMethodAsTrue.value();
    }
    public boolean isValid(Object object,
                           ConstraintValidatorContext constraintValidatorContext) {
        
        try {
            Class clazz = object.getClass();
            Method validate = clazz.getMethod(methodName, new Class[0]);
            return (Boolean) validate.invoke(object);
        } catch (Throwable e) {
            System.err.println(e);
        }
        return false;
    }
}
Since it is also most likely that you will have more than one method to validate, then an @AssertMethodAsTrueList would also be needed. The code are as follows:
package blogspot.soadev.validator;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Target(value={TYPE, ANNOTATION_TYPE})
@Retention(value=RUNTIME)
@Documented

public @interface AssertMethodAsTrueList {
    AssertMethodAsTrue[] value() default {};
}
With the @AssertMethodAsTrueList above you can have multiple @AssertMethodAsTrue on a single entity:
@AssertMethodAsTrueList({
    @AssertMethodAsTrue(value="isPassengerCountValid", message="Invalid passenger count!"),
    @AssertMethodAsTrue(value="isTirePressureIdeal")
})
public class Car {
    ...
    public void isPassengerCountValid(){...}
    public void isTirePressureIdeal(){...}
}

Related Posts

Cheers to the JSR 303 Bean Validation!

Layout Tips: ADF Faces RC - Panel Stretch Layout Component

There is a not so obvious setting for the width and height attributes of the facets of the Panel Stretch Layout Component and that is setting the values as "auto". It applies to the following attributes:
  • startWidth
  • endWidth
  • topHeight
  • bottomHeight
This is necessary especially if the component that you put in your top facet is expandable, a Query component for example. You would not most likely like to have scroll bars in your top facet, do you?
Below is a screen-shot image from JDeveloper with the property inspector of the panel stretch layout.

<af:panelStretchLayout id="psl1" topHeight="auto">
But please note of the following description of the topHeight attribute from the <af:panelStretchLayout> documentation:
the height of the top facet specified as a CSS length or auto such that this facet will no longer be stretched and instead will consume the initial offsetHeight given to its children by the browser. It is important to note that in an average page, a switch to a layout using automatic heights exhibited a 10 percent degradation in initial layout speed in Internet Explorer and a 5 percent degradation in Firefox. Results will vary but it is recommended that you use this sparingly in order to optimize your page. Also an automatic height will cause the facet child to not be stretched both vertically and horizontally. If necessary, you can make that automatic height child stretch horizontally by specifying a 100% width in the inlineStyle of that child. Note that many components such as the panelGroupLayout with layout set to scroll or vertical will have their own built-in stretched widths by default.

Monday, January 25, 2010

EJB and ADF model: (Error JBO-25221) SessionBean.dataProvider Method not supported

Problem: (Error JBO-25221) Method not supported.

I was puzzled by this error for sometime because the log do not give much information about the source of the error. The method is present in my SessionBeanLocal and the bindings was set in the ADF page definition file and yet, I am encountering this error. What I failed to realize is that I re-factored my session bean method to remove some unnecessary parameter but I overlooked to update my page definition file to remove such extra parameter.


Solution: Removing the extra parameter in the page definition file solves the issue.

Sunday, January 10, 2010

Error: CFGFWK-60184: Configuring WebLogic Domain : Multiple dependency matches

Error: CFGFWK-60184: The template you selected can't be applied because the following dependencies have not been satisfied:
Unresolved ORs:
Or for Oracle SOA Suite:11.1.1.0
[C:\Oracle\Middleware\Oracle_SOA1\common\templates\applications\oracle.soa_template_11.1.1.jar] 
Multiple dependency matches: 
Oracle SOA Management Extension:11.1.1.0
[C:\Oracle\Middleware\jdeveloper\common\templates\applications\oracle.soa.mgmt_template_11.1.1.jar]
 Oracle SOA Management Extension:11.1.1.0
[C:\Oracle\Middleware\oracle_common\common\templates\applications\oracle.soa.mgmt_template_11.1.1.jar]

Screen shot reference:

To resolve such issue, delete or relocate the file oracle.soa.mgmt_template_11.1.1.jar from %MiddlewareHome%\jdeveloper\common\templates directory to a folder outside of the middleware home and make some note in your notebook so you can put it back if needed. :)
Please see the following discussion in otn forums for your perusal. http://forums.oracle.com/forums/message.jspa?messageID=4016709#4016709

Update: I believe I came to this issue because I invoked the configuration wizard bundled with the integrated WLS of JDeveloper. I should have invoked the configuration wizard of the installed stand-alone weblogic server.
In Windows XP:
Start > All Programs > Oracle SOA 11g Home > Configure application server

Saturday, January 9, 2010

Error Starting Weblogic Admin Server: Could not reserve enough space for object heap

The first time that I run my weblogic admin server after installing and configuring oracle soa in weblogic 10.3.2, I encountered the following error:
Could not reserve enough space for object heap.
Could not create the Java virtual machine.

I resolved this by creating a new environment variable called EXTRA_JAVA_PROPERTIES with the following value "-Xms512m -Xmx512m".
From the JDeveloper 11g Release Notes:
Running applications with limited free memory (7343786)

Under certain circumstances, if you do not have enough free memory available, you may receive an error when running an application:

Error occurred during initialization of VM
Could not reserve enough space for object heap

Normally you would resolve this by adding -Xms and -Xmx arguments to the project's Run/Debug profile. However, there are existing entries for these settings in the WebLogic startup that will override the project's settings. The proper way to resolve this error is to add EXTRA_JAVA_PROPERTIES to your environment, as follows:

On Linux
setenv EXTRA_JAVA_PROPERTIES "-Xms512m -Xmx512m"

On Windows
set EXTRA_JAVA_PROPERTIES="-Xms512m -Xmx512m"

Important update to this post!

"-Xmx512" is not sufficient to run and test an application in a SOA server, because it would be incredibly slow. If you encounter the above issue using the default config of "-Xmx1024m", then try to decrease the number until it will work. There is no hard rule, you could try "-Xmx1000m" for instance. If it still doesn't work, then try decreasing the number again.

EJB and ADF: BUG! JPQLEntity.getAliasName() NullPointerException (EJB @Embedded Objects)

The title above is my posting on OTN Forum. I also filed a corresponding Service Request in Oracle Support to report such behavior.

I got an update that the corresponding bug was reproduced on there side. I am still waiting for the resolution of this and will update this post for any developments.

13 January 2010: I received the confirmation from Oracle Support that they filed (bug#9281552) for this issue.

Tuesday, January 5, 2010

EJB and ADF Faces RC: Inserting and Deleting Records to an Editable ADF Table that is Bound to an Entity (ArrayList) in a Managed Bean

My inspiration to write this post are the challenges that I have encountered in getting the selected row data, the method to remove rows and the inconsistent state of the table rows after removing a record. The Web User Interface Developers' Guide do not have a straight forward illustration on removing a row on a table that is not bound to an ADF Model/ADF BC type of data. Please note that I have not tried to run the codes below, but I have tried to demonstrate as much as possible the idea from the existing project that we have.

We have a requirement to have an editable master-detail information in which the master should be an editable form and the detail should be an editable table. This is a usual user-interface requirement for a accounting application especially on journal voucher entry screens (believe me here because I am a Certified Public Accountant :) ). In my encounter, the challenge was on the editable detail table. As much as possible I am sticking to the drag and drop from Data Controls panel style of creating the UI, but I cannot stick to it this time especially that this detail table has dependency on the master form (like "What's the applicable exchange rate defined in the master form?"- which is to be used by the rows of the detail table to translate an original currency Debits and Credits to base currency amounts) plus the fact that I need to conditionally set the visibility and required attribute of other components in the detail-table row based on the property of a selected account (an object on the same row).
Below is an illustrative code fragment to demonstrate the idea.
<af:panelCollection id="pc1">
  <f:facet name="toolbar">
    <af:toolbar id="t3">
      <af:commandToolbarButton text="Add"
                               id="ctb2"
                               actionListener="#{myBackingBean.addNewMyDetailObject}"/>
      <af:commandToolbarButton text="Remove"
                               id="ctb3"
                               actionListener="#{myBackingBean.removeSelectedMyDetailObject}"
                               immediate="true" />
    </af:toolbar>
  </f:facet>
  <af:table value="#{myBackingBean.myMasterObject.myDetailObjectList}"
                      var="row" id="t2"
                      partialTriggers="::ctb2 ::ctb3"
                      binding="#{myBackingBean.myDetailObjectRichTable}"
                      rowSelection="single"
                     
    <af:column sortable="false" headerText="Property 1" id="c1"
      <af:inputText value="#{row.myDetailObjectProperty1}" id="it1"/>
    </af:column>
      <af:column sortable="false" headerText="Property 2" id="c2"
    <af:inputText value="#{row.myDetailObjectProperty2}" id="it2"/>
      </af:column>
  </af:table>
</af:panelCollection>
I made a dummy backing bean class below to show the sample methods to insert and remove a row from the editable detail table:
package blogspot.soadev.view.backing;

import java.io.Serializable;

import java.util.List;

import javax.faces.event.ActionEvent;

import oracle.adf.view.rich.component.rich.data.RichTable;

public class MyBackingBean implements Serializable {
    private MyMasterObject myMasterObject;
    private RichTable myDetailObjectRichTable;
    
  public void addNewMyDetailObject(ActionEvent e) {
    MyDetailObject myDetailObject = new MyDetailObject();
    // add my deatil object to master
    myMasterObject.addMyDetailObject(myDetailObject);
    //can initialize myDetailObject properties if needed
    myDetailObject.setMyDetailObjectProperty1("property1 can be complex type");
    myDetailObject.setMyDetailObjectProperty2("property2 can be complex type");
  }
  public void removeSelectedMyDetailObject(ActionEvent e) {
    //get the selected row data
    MyDetailObject myDetailObject = (MyDetailObject)myDetailObjectRichTable.getSelectedRowData();
    //remove it from the master object
    myMasterObject.removeMyDetailObject(myDetailObject);
    //this my tip - refreshes the table stamping.
    //this is especilly needed if you conditionally set the attributes 
    //of other components (like visibility, rendered, required, etc)
    //if you will not invoke this, you will have inconsistent table row state.
    myDetailObjectRichTable.resetStampState();
  }


  public void setMyDetailObjectRichTable(RichTable myDetailObjectRichTable) {
    this.myDetailObjectRichTable = myDetailObjectRichTable;
  }

  public RichTable getMyDetailObjectRichTable() {
    return myDetailObjectRichTable;
  }

  public void setMyMasterObject(MyMasterObject myMasterObject) {
    this.myMasterObject = myMasterObject;
  }

  public MyMasterObject getMyMasterObject() {
    return myMasterObject;
  }
}

class MyDetailObject{
    private MyMasterObject myMasterObject;
    private Object myDetailObjectProperty1;
    private Object myDetailObjectProperty2;

  public void setMyMasterObject(MyMasterObject myMasterObject) {
    this.myMasterObject = myMasterObject;
  }

  public MyMasterObject getMyMasterObject() {
    return myMasterObject;
  }

  public void setMyDetailObjectProperty2(Object myDetailObjectProperty2) {
    this.myDetailObjectProperty2 = myDetailObjectProperty2;
  }

  public Object getMyDetailObjectProperty2() {
    return myDetailObjectProperty2;
  }

  public void setMyDetailObjectProperty1(Object myDetailObjectProperty1) {
    this.myDetailObjectProperty1 = myDetailObjectProperty1;
  }

  public Object getMyDetailObjectProperty1() {
    return myDetailObjectProperty1;
  }
}

class MyMasterObject{
    private List<MyDetailObject> myDetailObjectList;  
    public void addMyDetailObject(MyDetailObject myDetailObject){
          getMyDetailObjectList().add(myDetailObject);
          myDetailObject.setMyMasterObject(this);
    }
    public void removeMyDetailObject(MyDetailObject myDetailObject){
        getMyDetailObjectList().remove(myDetailObject);
        myDetailObject.setMyMasterObject(null);
    }

    public void setMyDetailObjectList(List<MyDetailObject> myDetailObjectList) {
      this.myDetailObjectList = myDetailObjectList;
    }

    public List<MyDetailObject> getMyDetailObjectList() {
      if(myDetailObjectList == null){
          myDetailObjectList = new ArrayList<MyDetailObject>();
      return myDetailObjectList;
    }
}
Please note of my tip on the table resetStampState() method above.
You maybe asking by now- "Where is the EJB part?", well, my master object is bound to an EJB DataControl ;) .

Oracle UI Shell: java.lang.InstantiationException TabContext$TabSelectionActionListener

The title above is my posting on OTN Forum and was noted to be a known issue. Please see Richard Wright response here.

Update: March 08, 2010. I receive an email that the fix will be available thru Check for Updates in the next two weeks.

Friday, January 1, 2010

Attn. JDeveloper Team: Painful to Drag an EJB DataControl as a Form (Ouch!)

The title above is my posting on OTN and was acknowledge as a bug with ticket no. 9248820. To see the post, click here.