Moving my blog to a new location

I moved my blog 3 months ago to www.reyjexter.com. In addition to java and jboss related stuff, I'll also be blogging about django, python and some personal stuffs. Please check

After a spending about 2 days researching on the HttpRequestMethodNotSupportedException thrown when running AbstractController.handleRequest in my test, I decided to view spring source code to see the real cause of this problem.

The problem was when creating MockHttpServletRequest, it doesn't set a default method name. To solve this problem, I simply added a request method type on the mock request object. See the following code:

request = new MockHttpServletRequest();
request.setMethod("POST");

Customizing spring security

One problem I encountered while trying to configure spring security is customizing it based on my own preferences. The default setup uses j_spring_security_login as the login page and j_spring_security_logout as the logout page. Although the default setup is enough to create a secured application, its not what I wanted. What I want is to configure spring security based on my own preferences, based on my own rules.

This is the login controller that i customized :

public class LoginController extends AbstractController {

@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {
ModelAndView mav = new ModelAndView();

SecurityContext securityContext = SecurityContextHolder.getContext();
Authentication auth = securityContext.getAuthentication();
String login = request.getParameter("login");

if(login != null && login.equals("1")) {
GrantedAuthority grantedAuthority = new GrantedAuthorityImpl("ROLE_ADMIN");
UserAuthentication userAuth = new UserAuthentication("rey", "q", new GrantedAuthority[]{grantedAuthority});
securityContext.setAuthentication(userAuth);
}

return mav;
}
}


And the applicationContext-security.xml :
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">

<security:global-method-security secured-annotations="enabled">
</security:global-method-security>

<security:http auto-config="true" session-fixation-protection="none">
<!-- <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" /> -->

<security:intercept-url pattern="/login.htm" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<security:intercept-url pattern="/css/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<security:intercept-url pattern="/images/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />


<security:intercept-url pattern="/**" access="ROLE_ADMIN" />
<security:remember-me user-service-ref="jdbcDaoImpl" />
<security:form-login login-page="/login.htm"/>
</security:http>

<security:authentication-provider user-service-ref="jdbcDaoImpl" />

</beans>

You can use http://tuckey.org/urlrewrite/ to rewrite the url of your java web application. This works when used with any java framework or even plain servlet.

I was trying to integrate spring security on my application but got a bit disappointed with it. Comparing it to jboss rules engine (drools), I find spring security a bit harder to be understood. The documentation and example is not very clear, most of the example on the documentation covers only xml based configuration and It didnt cover programmatic usage of the library.

Although its too early to conclude which one is better, right now I feel that jboss rules engine is a better choice since its much easier to use and understand. But anyway I'm gonna continue playing around with spring security because I may have missed something.

rolling back transaction

Annotating the method with the following:

@Transactional(readOnly=false, propagation=Propagation.NESTED)

will cause the transaction to wait until all sub transaction is completed. If any of the sub transaction fails, the global transaction will fail as well causing everything to be rolled back

After spending a couple of hours configuring this kind of setup, I was able to make my application run. Though there are some noticeable changes to when setting up application using struts/spring/hibernate or seam/ejb/jsf, I was able to learn some few things and they are the following:

1. using stereo type annotations (@Service, @Repository) is okay but not @Controller because it doesn't offer a very flexible way to configure controllers.

2. When using hibernate as persistence provider, it uses javassist to modify the java byte code.

3. persistence.xml should be placed on classes/META-INF not on web/META-INF (for tomcat users) because some very weird thing happens

4. Using spring mvc is much simpler than struts because the dependencies are not too many and by default a spring application context is already available when initializing a dispatcher servlet.

5. No need to use load time weaver when using hibernate as persistence provider.

Blogging Spring

Starting on the 3rd week of may, I'll work for ideyatech, a company that uses spring framework as its main technology. I'll be posting topics about spring and related technologies that is usually used with it.

Though I'm more of an seam guy now, working with spring will help me see the real difference between ejb/seam and spring. By working with both frameworks, I can determine the pros and cons of each framework and maybe in the future use them at the same time.

In the following days, I'll be posting more about Spring MVC, Spring Webflow and probably Spring Security (also known as ACEGI Security)

JBoss Tools on Ubuntu 8.04

I finished the installation of Ubuntu 8.04 last night. I just became a 100% open source developer by completely dumping windows. The installation was not very straight forward because I encountered several problems with eclipse running on Ubuntu. The following are the things I needed to solve while trying to install my Java development tools:

1. Eclipse keeps on crashing

This problem was really annoying because eclipse keeps on crashing every 5-10 minutes.

Solution:

Just add this at the end of your eclipse.ini (considering that no previous modification to that file was made):

-XX:MaxPermSize=90M

You will need to adjust the size depending on your computers memory.


2. Cannot open any file with JBoss Tools HTML Editor

When opening any file using JBoss Tools HTML Editor, I get a message box with the following error:

/home/jexter/app/eclipse/plugins/org.mozilla.xulrunner.gtk.linux.x86_1.8.1.3-20070904/xulrunner/libjavaxpcomglue.so: libstdc++.so.5: cannot open shared object file: No such file or directory

Solution:

Just install libstdc++5 by simply running this:

apt-get install libstdc++5

Don't forget to update your packages first.

When using seam framework and ajax4jsf, there is a bug when trying to re render an area using aj4:poll. Here is my code:

<h:outputText id="currentDateTime" value="#{currentDatetime}" styleClass="dateTime">
<s:convertDateTime pattern="MMMM dd, yyyy - hh:mm:ss a"/>
</h:outputText>

<h:form>
<a4j:poll interval="1000" reRender="currentDateTime" eventsQueue="timerQueue"></a4j:poll>
</h:form>


The solution is not yet clear as some say they need to tweak the concurrent-request-timeout in components.xml and others say that you need to simply make sure that the ajax request is not aschronous by using the eventsQueue property. Although the idea worked for me, some knowledgeable people say that tweaking those things depends on app by app.

Here are some useful links:

http://sfwk.org/Community/ConversationEndedTimedOutOrWasProcessingAnotherRequest
http://docs.jboss.com/seam/2.0.1.GA/reference/en/html/conversations.html#d0e5208

Ajax4JSF is a library that easily adds ajax functionality to existing jsf components. As oppose to Icefaces which is a set of jsf components that already have built in ajax functionalities, Ajax4JSF offers a much flexible way to add ajax functionalities to jsf components. It offers refreshing of display without the need to refresh the entire form. On the downside, Ajax4JSF is harder to use for very complex jsf components.

Using Ajax4JSF in seam 2.0 is easy. Just remove the line in your faces-config.xml:

<view-handler>com.sun.facelets.FaceletViewHandler</view-handler>
and add the following code on your web.xml just aboe the seam listener definition:
<context-param>
<param-name>org.ajax4jsf.VIEW_HANDLERS</param-name>
<param-value>com.sun.facelets.FaceletViewHandler</param-value>
</context-param>
You will also need to define the following on you xml schema:
xmlns:a4j="https://ajax4jsf.dev.java.net/ajax
The following code is an example of a simple clock functionality that updates its time by polling / reRendering the component. I didnt use a backing bean on this example:

<h:outputText id="currentDateTime" value="#{currentDatetime}" styleClass="dateTime">
<s:convertDateTime pattern="MMMM dd, yyyy - hh:mm:ss a"/>
</h:outputText>

<h:form>
<a4j:poll interval="1000" reRender="currentDateTime"></a4j:poll>
</h:form>

When using JBoss Tools 2.0.0 GA, the generated test project doesn't allow me to provide a custom persistence.xml. I'm not sure if this is a bug or the feature is not yet included on the given version. The persistence.xml being used when the application is deployed and when running test is the same. So what I did is update the hbm2ddl.auto property of the projectname-ejb/META-INF/persistence.xml to create/create-drop when running test and then when deploying the application, i switch it back to update.

Right now I don't want to waste my time just figuring out how to run test that uses a different persistence context. I have already spent 2 days just doing that but nothing happened. Its either I wait for a major JBoss Tools update or I'll try solving the problem again once I get some free time.

The following lines of code did not work as I expected:

Date monthStartDate = null;
Date monthEndDate = null;
dateTimeUtil.fillStartAndEndDate(date, monthStartDate, monthEndDate);

getLog().info("START: " + monthStartDate);
getLog().info("END: " + monthEndDate);


And the fillStartAndEndDate method:

public void fillStartAndEndDate(Date date, Date start, Date end) {
DateTime dateTime = new DateTime(date.getTime());

int startDay = dateTime.dayOfMonth().getMinimumValue();
DateTime startDate = new DateTime(dateTime.getYear(), dateTime.getMonthOfYear(), startDay, 0 ,0 ,0 ,0);
int endDay = dateTime.dayOfMonth().getMaximumValue();
DateTime endDate = new DateTime(dateTime.getYear(), dateTime.getMonthOfYear(), endDay, 0 ,0 ,0 ,0);

start = jodaDateTimeToJavaDate(startDate);
end = jodaDateTimeToJavaDate(endDate);
}


The results were the following:

START: null
END: null


This is one of those very basic things I sometimes overlook. At first, I thought that object reference in java works the same as the object reference in c++. In java, after creating a new instance of the object, the object (start param variable on the example) is not anymore pointing to the same reference which makes the method's local variable have a different value from the one that was originally passed.

I've written a pom.xml that will emanage the dependencies using maven. The following is my pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:artifact="antlib:org.apache.maven.artifact.ant"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

<modelVersion>4.0.0</modelVersion>
<groupId>com.reyjexter</groupId>
<artifactId>exacto</artifactId>
<name>exacto</name>
<version>1.0</version>
<packaging>war</packaging>

<repositories>
<repository>
<id>jboss</id>
<name>The JBoss maven repo</name>
<url>http://repository.jboss.com/maven2/</url>
</repository>
</repositories>

<parent>
<groupId>org.jboss.seam</groupId>
<artifactId>root</artifactId>
<version>2.0.1.GA</version>
</parent>

<build>
<finalName>exacto</finalName>
<plugins>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.1</version>
<executions>
<execution>
<phase>generate-sources</phase>
<configuration>
<tasks>

<echo>***Deleting WEB-INF/lib dir</echo>
<delete>
<fileset dir="web/WEB-INF/lib" includes="**/*.jar"/>
</delete>

</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.0</version>
<configuration>
<webappDirectory>/web</webappDirectory>
</configuration>
</plugin>

</plugins>
</build>

<dependencies>
<dependency>
<groupId>org.jboss.seam</groupId>
<artifactId>jboss-seam</artifactId>
<exclusions>
<exclusion>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
</exclusion>
<exclusion>
<groupId>javax.el</groupId>
<artifactId>el-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.jboss.el</groupId>
<artifactId>jboss-el</artifactId>
</exclusion>
<exclusion>
<groupId>jboss</groupId>
<artifactId>javassist</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>org.jboss.seam</groupId>
<artifactId>jboss-seam-ui</artifactId>
</dependency>

<dependency>
<groupId>com.sun.facelets</groupId>
<artifactId>jsf-facelets</artifactId>
</dependency>

<dependency>
<groupId>commons-digester</groupId>
<artifactId>commons-digester</artifactId>
<version>1.8</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>org.jboss.seam</groupId>
<artifactId>jboss-seam-debug</artifactId>
<version>2.0.1.GA</version>
</dependency>

<dependency>
<groupId>org.richfaces.framework</groupId>
<artifactId>richfaces-api</artifactId>
<version>3.1.3.GA</version>
<exclusions>
<exclusion>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>org.richfaces.framework</groupId>
<artifactId>richfaces-impl</artifactId>
<version>3.1.3.GA</version>
<exclusions>
<exclusion>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
<exclusion>
<groupId>javax.faces</groupId>
<artifactId>jsf-impl</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</exclusion>
<exclusion>
<groupId>javax.faces</groupId>
<artifactId>jsf-api</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>org.richfaces.ui</groupId>
<artifactId>richfaces-ui</artifactId>
<version>3.1.3.GA</version>
<exclusions>
<exclusion>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
<exclusion>
<groupId>javax.faces</groupId>
<artifactId>jsf-impl</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</exclusion>
<exclusion>
<groupId>javax.faces</groupId>
<artifactId>jsf-api</artifactId>
</exclusion>
</exclusions>
</dependency>

</dependencies>

</project>

The code simply removes the jar libraries from web/WEB-INF/lib and copies the maven dependencies to that folder.

I'll be posting a different configuration for ear and ejb jar in a couple of days

New EBJ 3 book

Knowledge in EJB is very important when studying seam framework because the framework itself was designed to be tightly coupled with ejb (although pojo's can also be used when developing applications, i think seam works better with ejb).

A week ago, the book I ordered from amazon arrived. The book entitled "EJB 3 In Action" from manning publishing covers the basics and important parts of ejb framework that is commonly used. Having read the book "Hibernate In Action" book from the same publisher, I think this book will be easily understood by people new to ejb 3.

Here are fresh from the box screenshots :D











Joda time and Seam / EJB

To use joda time libraries in seam project, simply copy joda-time-1.5.jar to PROJECTNAME-ear project folder and add the following in your application.xml:

<module>
<java>joda-time-1.5.jar</java>
</module>


When restarting jboss app server, the library for some unknown reason is not copied to deploy directory and Exception saying that joda time library cannot be found. Just copy the jar for to
PROJECTNAME-ear.ear folder in jboss deploy dir (for exploded deployment only)

I was trying to look for an easier way to clone objects (easier than using java.lang.Cloneable class) and I found out that using the jboss serialization library is easier and faster. The following code shows how to clone an object:

try {
JBossObjectOutputStream jbossSerializer = new JBossObjectOutputStream(null);
User newUser = (User) jbossSerializer.smartClone(user);
System.out.println(newUser);
}
catch(Exception e) {
System.out.println("EXCEPTION CAUGHT: " + e.getMessage());
}


using jboss serialization, you can also clone "Non serializable" objects.

you will need jboss-serialization.jar


Reference:

http://blogs.jboss.com/blog/clebert/

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