Using hibernate validation, we can decouple the validation rules and at the same time make it reusable for future projects. For example we want to validated if the username given already exist on the database and usually we just put our validation logics on the session bean or action (in struts). At the start of the project this looks ok but as the project progress and some new specification changes, new functionalities are added and some parts of your code gets refactored things get a bit messier.

Instead of simply dumping all the validation logic on the session bean we can create a custom hibernate validator which later can be used by annotating the getter of the entity property. Below is my code to validate if the username if it already exist on my database.

Username.java - The validator annotation definition

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ValidatorClass(UsernameValidator.class)
public @interface Username {
String message() default "Username already exists";
}


UserValidator.java - The validator class implementation

public class UsernameValidator implements Validator, Serializable{

private static final long serialVersionUID = -1458203631809206211L;

public void initialize(Username parameters) {
}

public boolean isValid(Object value) {
UserHome userHome = (UserHome) Component.getInstance("userHome");
User user = userHome.findUser((String)value);

// return true if no user with the given value was found
if(user == null) {
return true;
}

// return true if the user retrieved is equals to the current instance in home
if(user.getId() == userHome.getInstance().getId()) {
return true;
}

// return false if the username exist on our database
return false;
}

}
User.java - and finally, the entity class

public class User extends BaseEntity {

private static final long serialVersionUID = 6148649482941380604L;
private String username;

@Length(min=3, max=32, message="Username should be 3-32 characters")
@NotNull
@Username
public String getUsername() {
return username;
}
}
The validation code above simply tries to retrieve the user from database. If it returned null it means that no user with the given user name exist to it returns true (meaning the validation is successful). If a user with the given username is found, it checks if the user instance from userHome component is the same so that the validation will still be successful if we try to save it without modifying anything. Returning false will cause the validation process to return error message which can be later display by using in our xhtml.


References:

hibernate docs

hibernate validator source codes


Extending EntityQuery in seam 2.0.1 GA is not working properly. For some reason, the 'firstResult' is not injected by default and isNextExists() method always return false. The solution i found was to override both setFirstResult() and isNextExists() method. I manually injected the firstResult request context parameter, created an implementation of isNextExists() and everything seems to be working. Here is my EntityQuery subclass:

@Name("userList")
public class UserList extends EntityQuery {

private static final long serialVersionUID = 4676553441988735518L;

public UserList() {
setMaxResults(2);
}

@Override
public String getEjbql() {
return "select user from User user";
}

@RequestParameter("firstResult")
@Override
public void setFirstResult(Integer firstResult) {
if(firstResult==null) {
firstResult = 0;
}
super.setFirstResult(firstResult);
}

@Override
public boolean isNextExists() {
if(getFirstResult() + getMaxResults() < getResultCount()) {
return true;
}
return false;
}
}


And my xhtml code:


<s:link view="/userList.xhtml" value="Previous" rendered="#{userList.previousExists}">
<f:param value="#{userList.previousFirstResult}" name="firstResult" />
</s:link>

<s:link view="/userList.xhtml" value="Next" rendered="#{userList.nextExists}">
<f:param value="#{userList.nextFirstResult}" name="firstResult" />
</s:link>

I know this topic isn't about j2ee but i'm lately amazed by how system virtualization market have been growing. For the past few weeks, Sun Microsystems acquired Innotek, the creator of virtual box, an open-source counter part of VMWare. Today, Novell just bought PlateSpin (a company that focuses on virtualization systems).

But what is virtualization anyway? I think it's a way of doing something without the physical existence of the required thing or a way to do business without the existence of the system in the same location.

One of the ideas that started popping on my mind is what I call "Social Network Business Applications". These are applications that help businesses manage their daily work while at the same time making it "shareable" between different locations.

Anyway I'll talk more about these ideas later because I still need to think harder about them.

References: http://en.wikipedia.org/wiki/Virtualization

I was trying my first integration test but just using the default generated test class and xml meta data by jboss tools, i get the following error:

ERROR [org.jboss.kernel.plugins.dependency.AbstractKernelController] Error installing to Instantiated: name=DeploymentFilter state=Described
java.lang.IllegalStateException: Class not found: [Ljava.lang.String;
at org.jboss.metadata.spi.signature.Signature.stringsToClasses(Signature.java:174)

i tried the following things:

1. followed this http://wiki.jboss.org/wiki/Wiki.jsp?page=ClassNotFoundJava.lang.StringInJDK6
2. downloaded jboss embedded beta
3. upgraded to seam 2.1.0 AI

none of them worked for me.

lastly, i tried downloading seam 2.0.1 GA and installed jdk 1.5. i configured the test project's compiler compliance level to 5.0 instead of 6.0 (6.0 default for some reason. maybe because my default jdk is 1.6) and the result were so much better.

to remove the error message saying something like this:
Could not instantiate Seam component: authenticator
drools related libraries needs to be included since we are using the rule based engine and Identity class is part of it. just include the seam/lib/drools-core.jar, seam/lib/drools-compiler.jar and seam/lib/core.jar.

after copying the drools related libraries and executing the test, a different kind of error is thrown. this time an error saying that the "security.drl is missing" you will need to copy that file from seam/seam-gen/resource/security.drl and place it to projectname-test/bootstrap/deploy/ folder.

run it again and the test will be successful!

embedded jboss is needed when testing seam components or ejb's but based on the jboss seam integration testing documenation, the stable version have problems when using jdk 1.6. since there are compatability issues when testing using seam 2.0 GA on jdk 1.6, i think staying with 2.0.1GA and jdk 1.5 is better at the moment.

After creating a new project using JBoss Tools 2.0.0 GA, Seam 2.0.0 GA and tried deploying the application, I encountered this problem:

java.lang.RuntimeException: error while reading /WEB-INF/components.xml
at org.jboss.seam.init.Initialization.initComponentsFromXmlDocument(Initialization.java:136)
at org.jboss.seam.init.Initialization.create(Initialization.java:86)
at org.jboss.seam.servlet.SeamListener.contextInitialized(SeamListener.java:34)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3856)

and somewhere below the stack trace...


Caused by: java.lang.IllegalArgumentException: Exception setting property org.jboss.seam.core.init.jndiPattern on component org.jboss.seam.core.init. Expression @jndiPattern@ evaluated to null.
at org.jboss.seam.init.Initialization.installComponentFromXmlElement(Initialization.java:407)
at org.jboss.seam.init.Initialization.installComponentsFromXmlElements(Initialization.java:257)
at org.jboss.seam.init.Initialization.initComponentsFromXmlDocument(Initialization.java:132)
... 138 more


i think the problem here was when building the application. the value of @jndiPattern@ in components.properties should replace the same constant name defined in components.xml but for some reason, it did not.

my simple solution (although not very elegant) is to hardcode the value in components.xml. so instead of using @jndiPattern@ i copied its value from components.properties

Intro

I started this blog because I want to keep track of my progress and at the same time share the things I'm learning while studying java ee. At the moment, I'll be concentrating on studying EJB 3.0, JSF, JBoss Seam Framework and other related technologies to JBoss.

I've chosen to go for EJB instead of spring because I believe that the topics concerning EJB is broader than that of the spring framework. Also, I feel more security and stability with technologies that follow the standard specifications. EJB does, so I'll go for it.

I would like to thank my fiancee for creating a very nice logo for me (the one you see at the upper right part of this page). She designed it using the same colors used in the JBoss logo.

Newer Posts Home

Blogger Template by Blogcrowds