Monday 10 December 2012

Left shift <<, Right shift >> and Unsigned right shift >>>

The left shift operator, <<, shifts all of the bits in a value to the left a specified number of times. For each shift left, the high-order bit is shifted out (and lost), and a zero is brought in on the right.

For example,

int value = -49;
System.out.println(Integer.toBinaryString(value));
System.out.println(Integer.toBinaryString(value << 1));
System.out.println(Integer.toBinaryString(value << 8));
System.out.println(Integer.toBinaryString(value << 31));
System.out.println(Integer.toBinaryString(value << 32));

Result is:

11111111111111111111111111001111
11111111111111111111111110011110
11111111111111111100111100000000
10000000000000000000000000000000
11111111111111111111111111001111

It is interesting to note that when you left shift a value 32 bits, the result is not 0 as you may have expected. It turns out the shift distance is calculated mod 32. So value << 32 is exactly the same as value << 0 (do nothing).

What about left shift a negative value?

System.out.println(Integer.toBinaryString(value << -1));
System.out.println(Integer.toBinaryString(value << -24));

Result is:

10000000000000000000000000000000
11111111111111111100111100000000

You can see value << -1 is exactly the same as value << 31, value << -24 is exactly the same as value << 8.

The right shift operator, >>, shifts all of the bits in a value to the right a specified number of times. For each right left, the low-order bit is shifted out (and lost), and a zero is brought in on the left if the top bit is 0 (positive number), a one is brought in on the left if the top bit is 1(negative number).


int value = -49;
System.out.println(Integer.toBinaryString(value));
System.out.println(Integer.toBinaryString(value >> 1));
System.out.println(Integer.toBinaryString(value >> 8));
System.out.println(Integer.toBinaryString(value >> 31));
System.out.println(Integer.toBinaryString(value >> 32));
value = 49;
System.out.println(Integer.toBinaryString(value));
System.out.println(Integer.toBinaryString(value >> 1));
System.out.println(Integer.toBinaryString(value >> 8));
System.out.println(Integer.toBinaryString(value >> 31));
System.out.println(Integer.toBinaryString(value >> 32));

Result is:

11111111111111111111111111001111
11111111111111111111111111100111
11111111111111111111111111111111
11111111111111111111111111111111
11111111111111111111111111001111
110001
11000
0
0
110001

When the shift distance is 32, just like left shift operation, it has no effect. When the shift distance is negative, the behavior is similar to that of left shift operation --- e.g. value >> -1 is the same as value >> 31.

The unsigned right shift operator, >>>, shifts all of the bits in a value to the right a specified number of times. For each right left, the low-order bit is shifted out (and lost), and a zero is always brought in on the left regardless the top bit is 0 (positive number) or 1 (negative number).


int value = -49;
System.out.println(Integer.toBinaryString(value));
System.out.println(Integer.toBinaryString(value >>> 1));
System.out.println(Integer.toBinaryString(value >>> 8));
System.out.println(Integer.toBinaryString(value >>> 31));
System.out.println(Integer.toBinaryString(value >>> 32));
value = 49;
System.out.println(Integer.toBinaryString(value));
System.out.println(Integer.toBinaryString(value >>> 1));
System.out.println(Integer.toBinaryString(value >>> 8));
System.out.println(Integer.toBinaryString(value >>> 31));
System.out.println(Integer.toBinaryString(value >>> 32));

Result is:

11111111111111111111111111001111
1111111111111111111111111100111
111111111111111111111111
1
11111111111111111111111111001111
110001
11000
0
0
110001

Monday 26 November 2012

Puzzle 6: Multicast

int i = -1;
byte b = (byte)i;
char c = (char)b;
int i2 = (int)c;

The value of the variable in binary format is:

i = 1111 1111 1111 1111 1111 1111 1111 1111
b = 1111 1111
c = 1111 1111 1111 1111
i2 = 0000 0000 0000 0000 1111 1111 1111 1111

So we can see, from char to int, the sign is not considered. Simply prefixing 0s will do it.

If you wish to keep the sign, you need to cast char to short

short s = (short)c;
int i3 = (int)s;

result is:

s = 1111 1111 1111 1111
i3 = 1111 1111 1111 1111 1111 1111 1111 1111

If you cast byte to char, and you don't want to keep the sign. e.g. you want to achieve the following effect.

b = 1111 1111
c = 0000 0000 1111 1111

You can use bit mask:

char c = (char)(b & 0xff);

b & 0xff is of type int, so effectively

b & 0xff = 0000 0000 0000 0000 0000 0000 1111 1111

Puzzle 5: What does it mean by Hex and Octal literals are negative if their high-order bit is set?

In the book, "Java Puzzle", Puzzle 5: The Joy of Hex, there is a bold line Hex and Octal literals are negative if their high-order bit is set to explain the number 0xcafebabe is equivalent to the decimal value -889275714.

So what does "high-order bit is set" mean?

"high-order bit" is the left most bit of a given type. For example, if type is integer, which has 32 bits, then the high-order bit is the 32nd bit counting from right to left.

The 32nd bit counting from right to left is 0 in the following case, so the number is a positive number

int max = Integer.valueOf("01111111111111111111111111111111", 2);
System.out.println(max);

The result is

2147483647

which happens to be the maximum integer number.

Now let's convert the Hex format number 0xcafebabe to binary format

String s = Integer.toBinaryString(0xcafebabe);

The result is

11001010111111101011101010111110

The high-order bit is 1, therefore, it is a negative number.

Monday 22 October 2012

Request, Flash, View Scope in Spring webflow


What is the difference among these 3 scopes?

According to the Java doc:

Request: Attributes placed in request scope exist for the life of the current request into the flow execution. When the request ends any attributes in request scope go out of scope.

Flash: Attributes placed in flash scope exist through the life of the current request and until the next view rendering. After the view renders, flash scope is cleared. Flash scope is typically used to store messages that should be preserved until after the next view renders.

View: Attributes placed in view scope exist through the life of the current view state and until the view state exits in a subsequent request. View scope is typically used to store view model objects manipulated over a series of Ajax requests.

I don't think I can see their distinction clearly from the definitions above. So I am going to run some experiments to find out myself.

In the spring-web-flow.xml, I create a <view-state>.

<view-state id="dummy">
    <on-entry>
        <set name="viewScope.viewScopeAttribute" value="'v'" />
        <set name="flashScope.flashScopeAttribute" value="'f'" />
        <set name="requestScope.requestScopeAttribute" value="'r'" />
    </on-entry>
</view-state>

the dummy.xhtml JSF page is very simple:

request scope: #{requestScopeAttribute}
flash scope: #{flashScopeAttribute}
view scope: #{viewScopeAttribute}

I was expecting to see all 3 attributes displayed, but the request scope attribute is missing.

Let's change the <view-state> to

<view-state id="dummy">
    <on-render>
        <set name="viewScope.viewScopeAttribute" value="'v'" />
        <set name="flashScope.flashScopeAttribute" value="'f'" />
        <set name="requestScope.requestScopeAttribute" value="'r'" />
    </on-render>
</view-state>

All 3 attributes display this time. why?

This is because every time Spring webflow needs to render a view, it will issue a redirect causing the view to be rendered in the subsequent GET request. This is useful because when the user hit Refresh or Back button, the browser won't give any warning.

The actions in <on-entry> occur during the first request and any attributes in this request's scope will have been blown off by the time the view is rendered. Because the view is rendered in the second request.

The actions in <on-render> occur during the second request, so the attributes in this request's scope will be kept when the view is rendered.

As for the difference between viewScope and flashScope, I really cannot tell any as long as they are in <view-state>.  I think they can be used interchangeably in <view-state>. (I could be very wrong here).

However, viewScope cannot be used in <action-state> or <decision-state>.

flashScope will retain in memory until after the view is rendered. For example:

<action-state id="dummy0">
    <on-entry>
        <set name="flashScope.flashScopeAttribute" value="'f'" />
    </on-entry>
    <evaluate expression="new java.lang.String()" />
    <transition to="dummy"/>
</action-state>
 
<view-state id="dummy" /> 

The flash scope attribute still displays on the page.

Sunday 21 October 2012

Spring Security form-login behind the scene

In Spring in Action 3rd Edition, chapter 9, Securing Spring, page 228, here is a summary of the main points on this page.

The filter is defined in web.xml as:

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
  
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

The name of the filter springSecurityFilterChain is significant, meaning that you cannot give it an arbitrary name or the Spring security framework won't be able to find this filter.

The DelegatingFilterProxy doesn't do much and delegate the work to a special filter known as FilterChainProxy.

The FilterChainProxy is a single filter that chains together multiple additional filters. These filters, along with the FilterChainProxy, are created by Spring based on the security configuration. We will never need to explicitly declare the FilterChainProxy bean, so we don't need to know the details.

Ok, this is the gist of the page. As much as it says we don't need to know the details, I still have a few questions in mind.

  • How does FilterChainProxy chain together multiple other filters?
  • Which filter checks whether the provided username and password match the true credential?
  • There is an implicit object known as 'currentUser' in Spring Webflow. At what scope (request, session, flow) is this object stored?


Part 1.  How does FilterChainProxy chain together multiple other filters?


I am going to use the booking-face Spring Webflow sample project.

Let's start deployment and put a break point at DelegatingFilterProxy.java @Line 226. 

this.delegate = initDelegate(wac);

Step into it. DelegatingFilterProxy.java @Line 326. 

Filter delegate = wac.getBean(getTargetBeanName(), Filter.class);

After this line is executed, we see delegate is an instance of FilterChainProxy, and it contains lots of filters already.

FilterChainProxy[ UrlMatcher = org.springframework.security.web.util.AntUrlPathMatcher[requiresLowerCase='true']; Filter Chains: {/**=[org.springframework.security.web.context.SecurityContextPersistenceFilter@10896d0, org.springframework.security.web.authentication.logout.LogoutFilter@e542a1, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@179763c, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@1416e4f, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@b11bbf, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@194aa64, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@13e985a, org.springframework.security.web.session.SessionManagementFilter@8475c4, org.springframework.security.web.access.ExceptionTranslationFilter@4fd3a5, 
org.springframework.security.web.access.intercept.FilterSecurityInterceptor@d03044]}]

It is easily seen that this FilterChainProxy bean has long been created and stored in the web application context. The ContextLoaderListener was in play and if interested, please refer to my article What does ContextLoaderListener do in Spring?

Now we put a break point at DelegatingFilterProxy.java @Line 259 and launch the application (by go to the url http://localhost:8080/booking-faces/spring/main).

invokeDelegate(delegateToUse, request, response, filterChain);

Step into it. DelegatingFilterProxy.java @Line 346

delegate.doFilter(request, response, filterChain);

Step into it. FilterChainProxy.java @134-149

FilterInvocation fi = new FilterInvocation(request, response, chain);
List<Filter> filters = getFilters(fi.getRequestUrl());

if (filters == null || filters.size() == 0) {
    if (logger.isDebugEnabled()) {
        logger.debug(fi.getRequestUrl() +
        filters == null ? " has no matching filters" : " has an empty filter list");
    }

    chain.doFilter(request, response);

    return;
}

VirtualFilterChain virtualFilterChain = new VirtualFilterChain(fi, filters);
virtualFilterChain.doFilter(fi.getRequest(), fi.getResponse());

This is the central part. It differs from an everyday Filter in that for an everyday filter, after you do some processing, you invoke chain.doFilter() to give other filters chance to do their work. A typical example is this CharacterEncodingFilter

protected void doFilterInternal(
        HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
        throws ServletException, IOException {

    if (this.encoding != null && (this.forceEncoding || request.getCharacterEncoding() == null)) {
        request.setCharacterEncoding(this.encoding);
        if (this.forceEncoding) {
            response.setCharacterEncoding(this.encoding);
        }
    }
    filterChain.doFilter(request, response);
}

The FilterChainProxy also has this line @Line 143, am I too blind to notice that? Actually this line will not be executed. To be precisely, not until all the spring created filters have done their job.

We can press F6 to verify. Line 137-146 are skipped, and we are at Line 148. We are going to step into Line 149. But before we do, I want to take note of the chain object in the method argument list. It is org.apache.catalina.core.ApplicationFilterChain@9a731a

virtualFilterChain.doFilter(fi.getRequest(), fi.getResponse());

FilterChainProxy.java @Line 355

nextFilter.doFilter(request, response, this);

Step into it. Now we are at the very first of the so called "additional filters". SecurityContextPersistenceFilter.java @Line 50.

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)

Inspect the chain object, it is org.springframework.security.web.FilterChainProxy$VirtualFilterChain@1d418d4. The chain object is no longer the one created by the Application server (Glassfish, in this case). It now becomes the VirtualFilterChain created by Spring.

This is how, even though not defined in web.xml, these "additional filters" got chained together to do their job. Had we defined them in web.xml, we wouldn't have needed VirtualFilterChain. But the web.xml would have exploded and that would be the last thing we want to see. (Configuration is really pain in the ass)


Part 2.  Which filter checks whether the provided username and password match the true credential?


It is the UsernamePasswordAuthenticationFilter.

Let's put a break point @Line 97.

return this.getAuthenticationManager().authenticate(authRequest);

Just press F7 to jump out of this method and we are at AbstractAuthenticationProcessingFilter.java @Line 205

authResult = attemptAuthentication(request, response);

Step down till @Line 219

successfulAuthentication(request, response, authResult);

Step into it. AbstractAuthenticationProcessingFilter.java @Line 293

SecurityContextHolder.getContext().setAuthentication(authResult);

Put the authentication information into security context. The security context is saved in a thread local object.

AbstractAuthenticationProcessingFilter.java @Line 302

successHandler.onAuthenticationSuccess(request, response, authResult);

Step into it...eventually it hits SaveContextOnUpdateOrErrorResponseWrapper.java @Line 73

doSaveContext();

This line saves the security context into session.

Here is some  pseudocode to describe the login process.

String username = getUsername(request);
String password = getPassword(request);
boolean loginSuccessful = authenticationManger.authenticate(username, password);
if (loginSuccessful){
     SecurityContext sc = new SecuirtyContext(username);
     SecurityContextHolder.set(sc);
     session.setAttribute("SecurityContextKey", sc);
     redirectToLoginSuccessPage();
}else{
     redirectToLoginFailurePage();
}

Since we already save the security context into the session,  why put it into SecurityContextHolder object again?

Because SecurityContextHolder put the security context into a thread local object. Any plain java class can easily access the security context by calling the static method SecurityContextHolder.get(); However, it is not so easy to grab a session for a plain java class.


Part 3.  There is an implicit object known as 'currentUser'. At what scope (request, session, flow) is this object stored?



The implicit object 'currentUser' can be used at Spring Expression Language in web flow xml file or JSP/JSF page.

e.g. main-flow.xml

<evaluate expression="bookingService.findBookings(currentUser?.name)" result="viewScope.bookings" result-type="dataModel" />

e.g. enterSearchCriteria.xhtml

<p:panel id="bookings" header="Your Hotel Bookings" rendered="#{currentUser!=null}" ...>


We can have a look at ImplicitFlowVariableELResolver.java and FlowVariablePropertyAccessor.java. Both put 'currentUser' as a key into a static map, and the value corresponding to 'currentUser' is an object that is connected to the request context. The request context holds the external context, which holds the security context.

So the attribute 'currentUser' is never explicitly put into any scope.

When the EL resolver sees 'currentUser', it will find it in the security context attached to the request context. There is an easy way to obtain the request context by calling RequestContextHolder.getRequestContext(). The RequestContextHolder, working similarly as the way SecurityContextHolder does, put the request context into a thread local object.

We learn from part 2 and part 3 that there are two ways to obtain the current user programmatically. Thanks to thread local, they are both very straightforward:

RequestContextHolder.getRequestContext().getExternalContext().getCurrentUser();

SecurityContextHolder.getContext().getAuthentication().getPrincipal();




Wednesday 17 October 2012

Using security namespace as the default namespace

In Spring in Action, 3rd edition, page 227, it says since the security-specific configuration is separated into a separate Spring configuration file, we can change the security namespace to be the primary namespace.

So old version:

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

    <security:http auto-config="true" use-expressions="true">
        ....
    </security:http>
</beans>

And new version:

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

    <http auto-config="true" use-expressions="true">
        ....
    </http>

</beans:beans>

One thing I don't understand is why change beans to beans:beans. Why does the top element need a namespace?

Then I try to remove the namespace, the XML complains "Cannot find the declaration of element 'beans'".

Well, after reading the article XML Schema: Understanding Namespaces, I come to understand that the scope of a namespace begins at the element where it is declared. Therefore, in the old version, the element beans is associated with the default namespace (http://www.springframework.org/schema/beans),  in the new version, if we remove the namespace for the beans element, the element will be associated with the security namespace. But of course, the security schema doesn't define a beans element. Hence the complaint of the XML.

Let me rename the prefix of the beans namespace so that it looks more clear.

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

    <http auto-config="true" use-expressions="true">
        ....
    </http>

</bean123:beans>


Tuesday 16 October 2012

on-entry vs. on-render in Spring Webflow

The action defined in <on-entry> is executed upon entering the state.

The action defined in <on-render> is executed before the view is rendered.

The distinction seems very clear but in practice, say you need to load some information from the database to be displayed, will you use <on-entry> or <on-render>?

Both seem to be legitimate choices. Does it really matter if the data is loaded upon entry or right before the view is rendered?

Well, the answer depends on whether you want the data to be reloaded if the page gets refreshed (including partially refreshed).

Let's see an example.

In web-flow.xml, we have a view-state.

<view-state id="dummy">
    <on-entry>
        <evaluate expression="dummy.onEntry()"></evaluate>
    </on-entry>
    <on-render>
        <evaluate expression="dummy.onRender()"></evaluate>
    </on-render>
</view-state>

Dummy.java

public class Dummy implements Serializable{
    private static final long serialVersionUID = 1L;
 
    public void onRender(){
        System.out.println("On Render");
    }
 
    public void onEntry(){
        System.out.println("On Entry");
    }
}

After the view is rendered on the browser, we will see in the console

On Entry
On Render

Now we refresh the page (i.e. press F5), we will see in the console

On Entry
On Render
On Render

So the on-entry action wouldn't be executed but on-render action still would.

Monday 15 October 2012

What does ContextLoaderListener do in Spring?

In web.xml, there is usually the following line

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

So what does ContextLoaderListener do exactly?

As the Spring API puts it:

Bootstrap listener to start up Spring's root WebApplicationContext. Simply delegates to ContextLoader.

I believe this sentence is too vague to visualize the responsibility this class takes on. So this article tries to break down the duties performed by this class.

In summary, ContextLoaderListener does three main tasks:
  • Create a web application context
  • Read bean definitions from application context xml
  • Instantiate and initialize beans based on the bean definitions and save the beans into the web application context.
I will give detailed explaination one by one.

1. Create a web application context


Upon the start of the deployment, callback method ContextLoaderListener.contextInitialized() will be invoked by the container or application server.

ContextLoaderListener.contextInitialized() will delegate the task of creating web application context to this.contextLoader.

ContextLoaderListener @Line 111

this.contextLoader.initWebApplicationContext(event.getServletContext());

ContextLoader.java @Line 281

this.context = createWebApplicationContext(servletContext);

After this line, the web application context is created. Pretty straightforward, isn't it? If we put the break point at the next line, we will see the class of this.context is XmlWebApplicationConext.

One things needs probing here:

Who gets to pick this particular implementation of the WebApplicationConext?

Spring has provided more than one implementations, including AnnotationConfigWebApplicationContext, GenericWebApplicationContext and StaticWebApplicationContext. How does XmlWebApplicationConext distinguish itself among all the candidates? Can we use our own implementation of WebApplicationContext should the need arises?

We need to step into the createWebApplicationContext() method.

ContextLoader.java @Line 333

Class<?> contextClass = determineContextClass(sc);

Step into this method, ContextLoader.java @Line 398

String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);

contextClassName is null because there is no such init parameter defined in web.xml

Then we have to fall back to the default value, ContextLoader.java @Line 411

contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());

The variable defaultStrategies is a Properties object, which holds a name-value pair:

{org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext}

When is the defaultStrategies  object loaded with this name-value pair and where is this information stored initially?

ContextLoader.java @Line 164-165

ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, ContextLoader.class);
defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);

The value of the constant DEFAULT_STRATEGIES_PATH is ContextLoader.properties, which resides at the same package of the same jar file (spring-web.jar) as ContextLoader does.

We can write our own implementation of WebApplicationContext and add a context-param entry to web.xml.

<context-param>
    <param-name>contextClass</param-name>
    <param-value>
        org.springframework.web.context.support.CustomerWebApplicationContext
    </param-value>
</context-param>

2. Read bean definitions from application context xml


In this part, 3 questions will be addressed.

1. Where in ContextLoader does reading bean definitions take place?
2. We know that the context-param entry for contextConfigLocation is optional, so where is the default context config location defined?
3. If we do add a context-param entry for contextConfigLocation in web.xml, where does the default value gets overwritten?

ContextLoader.class @Line 284

configureAndRefreshWebApplicationContext((ConfigurableWebApplicationContext)this.context, servletContext);

Reading bean definitions takes place here. OK, to be fair, lots of things take place here, also including instantiating and initializing beans.

We have to be a bit more specific about the location.

Let's step into this method. ContextLoader.class @Line 385

wac.refresh();

Further step into this method. The actual method body of refresh(); is in the super class of XmlWebApplicationContext: AbstractApplicationConext. Let's jump to Line 437.

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

This line does more than merely obtaining a bean factory as the method name suggests. It is also precisely where loading the bean definitions from the application context xml occurs. However, it won't instantiate the beans and put them to web application context yet.

Let's step into this method. AbstractApplicationContext.java @Line 526.

refreshBeanFactory();

Further step into this method. AbstractRefreshableApplicationContext.java @Line 128.

DefaultListableBeanFactory beanFactory = createBeanFactory();

This line creates a bean factory. It's empty yet. If you watch the variable in the debugger, you will find the beanDefinitionMap and beanDefinitionNames are empty. Step down to Line 131.

loadBeanDefinitions(beanFactory);

This line, unsurprisingly,  loads all the bean definitions.

Assume we don't have a context-param entry for contextConfigLocation in web.xml, we will eventually hit AbstractRefreshableConfigApplication.java @Line 100

return (this.configLocations != null ? this.configLocations : getDefaultConfigLocations());

this.configLocation = null because it's not defined in web.xml. So it falls back to default location, which is defined at XmlWebApplicationConext @Line 65.

public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml";

This tells us if you don't want to specify the contextConfigLocation context parameter in web.xml, you need to place the application context file under WEB-INF, and name it exactly -- applicationContext.xml

Now let's add a context-param entry for contextConfigLocation in web.xml, 

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/config/web-application-config.xml
    </param-value>
</context-param>

Restart deployment,  ContextLoader.java @Line 380-383

String initParameter = sc.getInitParameter(CONFIG_LOCATION_PARAM);
if (initParameter != null) {
    wac.setConfigLocation(initParameter);
}

The above line sets the path of the application context xml file. 

Let's jump out of the method and go back to AbstractApplicationContext.java @Line 440, and put a break point there.

prepareBeanFactory(beanFactory);

f you expand object beanFactory in the debugger, and inspect the instance variable beanDefinitionMap and beanDefinitionNames, you will find they are populated with values.

3. Instantiate and initialize beans based on the bean definitions and save the beans into the web application context


Now it is time we threw some bean definitions into the application context xml file and see how Spring instantiates them.

Let's start with something very simple. In the applicationContext.xml, add

<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

Now restart the deployment process, put a break point at AbstractApplicationContext.java @Line 465.

finishBeanFactoryInitialization(beanFactory);

All the beans are created here.

Step into the method, and pause at AbstractApplicationConext.java @Line 917

beanFactory.preInstantiateSingletons();

Step into it, put a break point at DefaultListableBeanFactory.java @Line 564

RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);

Inspect the beanName variable, we are only interested in it when it becomes 'BeanNameUrlHandlerMapping'

Then it hits DefaultListableBeanFactory.java @Line 585

getBean(beanName);

Given the bean name, the bean is instantiated through reflection. I was once puzzled by the fact that the returned bean is not assigned to any variable for further processing (like storing it to web application context). Would the bean be garbage collected?

If you debug into the getBean() method, you will reach AbstractAutowireCapableBeanFactory @Line 507-510.

addSingletonFactory(beanName, new ObjectFactory() {
    public Object getObject() throws BeansException {
        return getEarlyBeanReference(beanName, mbd, bean);
    }
});

Here, the created bean is put into the web application context. Therefore, the bean won't be garbage collected.

What does webflow:flow-registry tag do?

I have been studying the spring webflow's example project, booking faces, these days.

In webflow-config.xml, the definition of flowRegistry is as follows.


<webflow:flow-registry id="flowRegistry" flow-builder-services="facesFlowBuilderServices" base-path="/WEB-INF/flows">
    <webflow:flow-location-pattern value="/**/*-flow.xml" />
</webflow:flow-registry>


<faces:flow-builder-services id="facesFlowBuilderServices" development="true" />

The webflow namespace has long been baffling me. Is flowRegistry a bean? If it is, then why is it not defined in a typical way like

<bean id="flowRegistry" class="....">
    ...
</bean>

However, I have been too slack to find the answer. Now the addition of flow-builder-services="facesFlowBuilderServices" makes it more complex. Is this facesFlowBuilderServices a bean? If it is, why does it look so out of place?

All of a sudden, I just feel obliged to investigate the problem thoroughly.

I put a break point at DefaultListableBeanFactory.java @Line 564.

Here is the code from Line 562-564

List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
    for (String beanName : beanNames) {
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);

The variable beanNames holds, not surprisingly, all the bean names.

The variable bd contains the bean definition, which is derived from the application context xml.

When the program hits the break point, it's easily seen that both flowRegistry and facesFlowBuilderServices are among the bean names.

I keep pressing F8 until the variable beanName becomes flowRegistry.

I inspect the variable bd.

beanClass = org.springframework.webflow.config.FlowRegistryFactoryBean

Expand propertyValues -> propertyValueList -> elementData -> [0]

name = flowBuilderServices
value = <facesFlowBuilderServices>

Collapse [0] and expand [1]

name = basePath
value = /WEB-INF/flows

Collapse [1] and expand [3]

name = flowLocationPatterns
value = [/**/*-flow.xml]

OK, it is clear to see that the webflow:flow-registry tag defines the flowRegistry bean. If we wanted, we could define the bean in the traditional way, which is less succinct:

<bean id="flowRegistry" class="org.springframework.webflow.config.FlowRegistryFactoryBean">
    <property name="flowBuilderServices" ref="facesFlowBuilderServices" />
    <property name="basePath" value=" /WEB-INF/flows" />
    <property name="flowLocationPatterns" value="/**/*-flow.xml" />
</bean>

Let's do an experiment by taking out the flow-builder-services="facesFlowBuilderServices" bit off the flowRegistry bean definition and see if the flowBuilderServices will be null or some default value will be provided.

Repeat the same process, we will find

name = flowBuilderServices
value = <org.springframework.webflow.engine.builder.support.FlowBuilderServices#0>

A default value is provided.

We can employ the same approach to find out the difference between the default flowBuilderServices and facesFlowBuilderServices.

The class for both beans is org.springframework.webflow.engine.builder.support.FlowBuilderServices

The property viewFactoryCreator of the default flowBuilderServices is an instance of org.springframework.webflow.mvc.builder.MvcViewFactoryCreator.

The property viewFactoryCreator of the facesFlowBuilderServices is an instance of org.springframework.faces.webflow.JsfViewFactoryCreator.

One of the differences between MvcViewFactoryCreator and JsfViewFactoryCreator is that MvcViewFactoryCreator appends the extension '.jsp' to the view while JsfViewFactoryCreator  appends the extension '.xhtml' to the view.

Let's recapitulate the main points.
  • The <webflow:flow-registry> tag defines a flowRegistry bean.
  • The <faces:flow-builder-services> tag defines a facesFlowBuilderServices bean.
  • When flow-builder-services="facesFlowBuilderServices" is omitted, a default flowBuilderServices instance will be created. 

Wednesday 10 October 2012

Anonymous inner class

Here is an interface


public interface Factory {
    public Object getObject();
}


Here is the client code


public class Client {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Client client = new Client();
        Factory f = client.createFactory("abc");
        print(f);
    }
 
 
    private Factory createFactory(Object obj){
        //TODO
        return null;
    }
 
    private static void print(Factory factory){
        System.out.println(factory.getObject());
    }
}


How will you go about coding the createFactory(Object obj) method so that print(f) will yield the result "abc"?

The traditional approach is to create an implementation of Factory interface.

class FactoryImpl implements Factory{

    private Object o;
 
    public FactoryImpl(Object o) {
        super();
        this.o = o;
    }

    public Object getObject() {
        return o;
    }
 
}


Then create an instance of FactoryImpl

private Factory createFactory(Object obj){
    Factory factory = new FactoryImpl(obj);
    return factory;
}


The task gets much easier if we use anonymous inner class

No need to create a named class that implements the Factory interface. Instead...

private Factory createFactory(final Object obj){
    Factory factory = new Factory() {
        public Object getObject() {
            return obj;
        }
    };
    return factory;
}


There is one caveat: The argument obj must be declared as final. Or it doesn't compile.

Monday 8 October 2012

Class.getResourceAsStream() VS. ClassLoader.getResourceAsStream()


For Class.getResourceAsStream(String name), if the name parameter doesn't start with a "/", then it's a relative path to the class's package. If the name parameter starts with a "/", then it's an absolute path.

For ClassLoader.getResourceAsStream(String name), the name parameter is always an absolute path, and it can never start with a "/". If it does, the resource is never found.

If the file cannot be found, both methods return null and no exception is thrown.

The following program illustrates the difference.

Project structure











ResourceAsStream.java

public class ResourceAsStream {

    /**
     * @param args
     */
    public static void main(String[] args) {
        String path1 = "a.properties";
        String path2 = "/a.properties";
        String path3 = "test/a.properties";
        String path4 = "/test/a.properties";
  
        System.out.println("Class.getResourceAsStream()");
        InputStream is = ResourceAsStream.class.getResourceAsStream(path1);
        System.out.println(path1 + " " + (is != null));
        is = ResourceAsStream.class.getResourceAsStream(path2);
        System.out.println(path2 + " " + (is != null));
        is = ResourceAsStream.class.getResourceAsStream(path3);
        System.out.println(path3 + " " + (is != null));
        is = ResourceAsStream.class.getResourceAsStream(path4);
        System.out.println(path4 + " " + (is != null));
        System.out.println();
        System.out.println("ClassLoader.getResourceAsStream()");
        is = ResourceAsStream.class.getClassLoader().getResourceAsStream(path1);
        System.out.println(path1 + " " + (is != null));
        is = ResourceAsStream.class.getClassLoader().getResourceAsStream(path2);
        System.out.println(path2 + " " + (is != null));
        is = ResourceAsStream.class.getClassLoader().getResourceAsStream(path3);
        System.out.println(path3 + " " + (is != null));
        is = ResourceAsStream.class.getClassLoader().getResourceAsStream(path4);
        System.out.println(path4 + " " + (is != null));
  
    }

}


Result:

Class.getResourceAsStream()
a.properties true
/a.properties false
test/a.properties false
/test/a.properties true

ClassLoader.getResourceAsStream()
a.properties false
/a.properties false
test/a.properties true
/test/a.properties false


Thursday 4 October 2012

JSF 2.0 integrated with Spring 3 through annotation

JSF can certainly be integrated with Spring 3 through XML declaration, but this article illustrates the simplest way, annotation, to get the job done.

Project structure



















pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        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.demo</groupId>
    <artifactId>jsf-spring</artifactId>
    <packaging>war</packaging>
    <name>JSF Spring</name>
    <version>0.1</version>

    <dependencies>
  
        <!-- Spring framework -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>3.1.2.RELEASE</version>
        </dependency>
 
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>3.1.2.RELEASE</version>
        </dependency>

        <!-- JSF -->
        <dependency>
            <groupId>com.sun.faces</groupId>
            <artifactId>jsf-api</artifactId>
            <version>2.1.13</version>
        </dependency>
  
        <dependency>
            <groupId>com.sun.faces</groupId>
            <artifactId>jsf-impl</artifactId>
            <version>2.1.13</version>
        </dependency>
  
    </dependencies>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>


web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="WebApp_ID" version="3.0">

    <display-name>jsf-spring-web</display-name>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
 
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <listener>
        <listener-class>
            org.springframework.web.context.request.RequestContextListener
        </listener-class>
    </listener>

    <context-param>
        <param-name>javax.faces.PROJECT_STAGE</param-name>
        <param-value>Development</param-value>
    </context-param>

    <!-- JSF Mapping -->
    <servlet>
        <servlet-name>facesServlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>facesServlet</servlet-name>
        <url-pattern>*.xhtml</url-pattern>
    </servlet-mapping>
</web-app>


faces-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<faces-config
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
    version="2.0">

    <application>
        <el-resolver>
            org.springframework.web.jsf.el.SpringBeanFacesELResolver
        </el-resolver>
    </application>
</faces-config>


UserDaoImpl.java

package com.demo.dao;

import org.springframework.stereotype.Repository;

@Repository("userDao")
public class UserDaoImpl implements UserDao {

    @Override
    public String getMessage() {
        return "Hello";
    }

}


UserBean.java

package com.demo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.demo.dao.UserDao;

@Component("userBean")
@Scope("session")
public class UserBean {
 
    @Autowired
    private UserDao userDao;
 
    public String message(){
        return userDao.getMessage();
    }

    public UserDao getUserDao() {
        return userDao;
    }
}


Note UserBean is supposed to be the manage bean and yet there is no JSF annotation (such as @ManagedBean or @SessionScoped) at all.

applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.1.xsd">
 
    <context:annotation-config/>
 
    <context:component-scan base-package="com.demo.dao" />
    <context:component-scan base-package="com.demo.controller" />
 
</beans>


index.xhtml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html">

    <h:body>
        <h1>JSF 2.0 + Spring Example</h1>
            #{userBean.message()}
    </h:body>

</html>

Monday 24 September 2012

JPA Hibernate one-to-many bidirectional mapping on List

This article illustrates how to use JPA and Hibernate annotation to do one-to-many bidirectional mapping for ordered entities.

The One side is the Teacher entity

@Entity
public class Teacher {
 
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int id;
 
    @Column
    private String name;
 
    @OneToMany(cascade={CascadeType.ALL}, fetch=FetchType.EAGER)
    @JoinColumn(name="STU_ID")
    @IndexColumn(name="IDX")
    private List<Student> students = new ArrayList<Student>();
  
    public Teacher(String name) {
        super();
        this.name = name;
    }
 
    public Teacher() {
        super();
    }

    public void addStudent(Student s){
        students.add(s);
        s.setTeacher(this);
    }

    //Setters and getters
}

Note the Teacher class has a List of Students, not a Set of Students. The @IndexColumn annotation is used to specify which column in Student table to store the index.

The Many side is the Student entity

@Entity
public class Student {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int id;
 
    @Column
    private String name;
 
    @ManyToOne
    @JoinColumn(name="STU_ID", 
            insertable=false, updatable=false)
    private Teacher teacher;

    public Student(String name) {
        Super();
        this.name = name;
    }
 
    public Student() {
        super();
    }

    //Setters and getters 
}

The name attribute of @JoinColumn for Teacher and Student should match one another (in this case, it is "STU_ID").

Write a JUnit test case


public void testTeacherDao(){
    TeacherDao dao = (TeacherDao)applicationContext.getBean("teacherDao");
    Teacher teacher = new Teacher("t1");
    teacher.addStudent(new Student("s1"));
    teacher.addStudent(new Student("s2"));
    dao.save(teacher);
}            


Output:

Teacher table





Student table






This example works in Hibernate 4.1.7.

Wednesday 19 September 2012

Spring applicationContext.xml cheat sheet for creating transaction manager for resource local persistence unit

Spring 3.0.5 + Hibernate 3.4.0

Approach 1

Specify Connection properties in persistence.xml
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/persistence 
                         http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
        version="1.0">

     <persistence-unit name="hibernate-resourceLocal" transaction-type="RESOURCE_LOCAL">
         <provider>org.hibernate.ejb.HibernatePersistence</provider>
         <properties>
             <!-- Connection properties -->
             <property name="hibernate.connection.driver_class" value="org.apache.derby.jdbc.ClientDriver" />
             <property name="hibernate.connection.url" value="jdbc:derby://localhost:1527/c:\derbydb\mydb" />
             <property name="hibernate.connection.username" value="APP" />
             <property name="hibernate.connection.password" value="APP" />

             <property name="hibernate.dialect" value="org.hibernate.dialect.DerbyDialect" />
             <!-- create-drop, create -->
             <property name="hibernate.hbm2ddl.auto" value="update" />
             <property name="hibernate.show_sql" value="true" />
             <property name="hibernate.format_sql" value="true" />
             <property name="hibernate.connection.autocommit" value="true" />
         </properties>
    </persistence-unit>
</persistence>

applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee"
        xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans 
            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
            http://www.springframework.org/schema/jee 
            http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
            http://www.springframework.org/schema/context 
            http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/tx  
            http://www.springframework.org/schema/tx/spring-tx.xsd">

     <context:component-scan base-package="com.demo.dao" />

     <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
         <property name="persistenceUnitName" value="hibernate-resourceLocal"/>
     </bean>

     <tx:annotation-driven />
 
     <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
         <property name="entityManagerFactory" ref="entityManagerFactory" />
     </bean> 
 
</beans>

Approach 2

Specify Connection properties in applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee"
        xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans 
            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
            http://www.springframework.org/schema/jee 
            http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
            http://www.springframework.org/schema/context 
            http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/tx  
            http://www.springframework.org/schema/tx/spring-tx.xsd">

     <context:component-scan base-package="com.demo.dao" />

     <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
         <property name="dataSource" ref="dataSource"/>
         <property name="persistenceUnitName" value="default"/>
         <property name="jpaVendorAdapter">
             <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                 <property name="showSql" value="true"/>
                 <property name="generateDdl" value="true"/>
                 <property name="databasePlatform" value="org.hibernate.dialect.DerbyDialect"/>
             </bean>
         </property>
     </bean>
 
     <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
         <property name="driverClassName" value="org.apache.derby.jdbc.ClientDriver"/>
         <property name="url" value="jdbc:derby://localhost:1527/c:\derbydb\mydb"/>
         <property name="username" value="APP"/>
         <property name="password" value="APP"/>
     </bean>
 
     <tx:annotation-driven/>
 
     <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
         <property name="entityManagerFactory" ref="entityManagerFactory" />
     </bean>
</persistence-unit>



The persistence.xml is all but empty.
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/persistence 
                         http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
        version="1.0">
     <persistence-unit name="default"/>
</persistence>

Glassfish 3.1 + Spring 3.0 + JNDI

I am writing a web application deployed in Glassfish application server 3.1. The service bean is exposed as a Spring managed bean instead of an EJB. The service bean is injected with an EntityManager, the data source of which is obtained from JNDI.

Wiring Spring with JNDI in Glassfish is more difficult than I thought.

I come across some common exceptions on which there are tons of discussions online. However, I fail to find helpful answers.

Therefore I feel necessary to write this blog to provide a simple solution.

persistence.xml
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://java.sun.com/xml/ns/persistence 
     http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
     version="1.0">
     <persistence-unit name="jta" transaction-type="JTA">
         <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
         <jta-data-source>jdbc/myderby</jta-data-source>
         <properties>
             <property name="eclipselink.ddl-generation" value="create-tables" />
             <property name="eclipselink.ddl-generation.output-mode" value="database" />
             <property name="eclipselink.logging.parameters" value="true" />
             <property name="eclipselink.logging.level" value="FINE" />
         </properties>
     </persistence-unit>
</persistence>


applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee"
     xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
     xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/jee 
        http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx  
        http://www.springframework.org/schema/tx/spring-tx.xsd">

     <context:component-scan base-package="com.demo.controller" />
     <context:component-scan base-package="com.demo.dao" />

     <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
         <property name="persistenceUnitName" value="jta"/>
     </bean>

     <tx:annotation-driven />
 
     <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
         <property name="entityManagerFactory" ref="entityManagerFactory" />
     </bean>
  
</beans>

UserDao.java
@Repository("userDao")
public class UserDaoImpl implements UserDao {

     @PersistenceContext 
     protected EntityManager entityManager;
 
     @Transactional
     public void save(User user) {
         entityManager.persist(user);
     }
}

Deployment is fine. When dao is accessed at runtime, an exception is thrown:


java.lang.IllegalStateException:
Exception Description: Cannot use an EntityTransaction while using JTA.
     at org.eclipse.persistence.internal.jpa.transaction.JTATransactionWrapper.getTransaction(JTATransactionWrapper.java:65)
     at org.eclipse.persistence.internal.jpa.EntityManagerImpl.getTransaction(EntityManagerImpl.java:1153)
     at org.springframework.orm.jpa.DefaultJpaDialect.beginTransaction(DefaultJpaDialect.java:70)
     at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:332)
I change the transaction-type from "JTA" to "RESOURCE_LOCAL" in persistence.xml.

The result is even worse. Deployment is complaining:

SEVERE: Exception while preparing the app : The persistence-context-ref-name [com.demo.dao.UserDaoImpl/entityManager] in module [spring-mvc-jpa-jndi] resolves to a persistence unit called [jta] which is of type RESOURCE_LOCAL. Only persistence units with transaction type JTA can be used as a container managed entity manager. Please verify your application.

I am not surprised to see this exception though. Since this is a Java EE environment, the transaction type should only be JTA. So I change the transaction type back to JTA.

I then try a lot of approaches in vain until I see this article:

http://java.dzone.com/tips/how-use-glassfish-managed-jpa

The core value of the article is this single line:

<tx:jta-transaction-manager/>


I replace my transactionManager bean definition with this line and it works perfectly.

After some investigation, it turns out this line creates the transactionMananger instance from this class: org.springframework.transaction.jta.JtaTransactionManager.

So it also works if I replace this line with:

<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>


Now it is easy to explain why the previous transactionManager causes an exception.  Clearly the org.springframework.orm.jpa.JpaTransactionManager is the transaction manager for RESOURCE_LOCAL persistence unit while org.springframework.transaction.jta.JtaTransactionManager is the transaction manager for JTA persistence unit. The latter probably delegates all the hassle stuff such as "beginning transaction","committing" and "closing transaction" to the Java EE container while the former needs to do all this chore.

With only one persistence unit defined, I can further strip the applicationContext.xml down to the following final version.

<context:component-scan base-package="com.demo.controller" />
<context:component-scan base-package="com.demo.dao" />

<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"/>

<tx:annotation-driven />
 
<tx:jta-transaction-manager/>
I am using Spring 3.0.5.

Monday 17 September 2012

A bug in EclipseLink

I recently found a bug in EclipseLink JPA provider.

I posted the question and answer at Stackoverflow.

Let me summarize the problem here.

First, retrieve an entity from the database, call entityManager.merge() on this entity, change the entity's Id, call entityManager.merge() on this entity again. An exception will be thrown.

Note the above operations are not executed in the same transaction context. Rather, each merge() is executed within its own transaction.

Here is the pseudocode to illustrate the idea.


User user = userManager.find(1); 
userManager.merge(user); 
System.out.println("User is managed? "+userManager.contains(user);
user.setId(2);
userManager.merge(user);


The console outputs:

User is managed? false

Exception [EclipseLink-7251] (Eclipse Persistence Services - 2.1.3.v20110304-r9073): org.eclipse.persistence.exceptions.ValidationException
Exception Description: The attribute [id] of class [demo.model.User] is mapped to a primary key column in the database. Updates are not allowed.


userManager.contains() methods invokes the entityManager.contains() method, the fact that it returns false indicates the entity is not being managed. When switching the JPA provider from EclipseLink to Hibernate, it works fine. And according to the JPA specification, it shouldn't throw any exception in this scenario. I believe this bug has manifested itself in other forms. I have found several articles discussing this exception. If you want to reproduce this error, this blog presents one of the simplest approaches.

Thursday 13 September 2012

Persistence.xml cheat sheet for Hibernate, EclipseLink and OpenJPA

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence 
             http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
 version="1.0">
 
 <persistence-unit name="jta" transaction-type="JTA">
  <provider>org.hibernate.ejb.HibernatePersistence</provider>
  <jta-data-source>jdbc/myderby</jta-data-source>
 </persistence-unit>

 <persistence-unit name="hibernate-resourceLocal" transaction-type="RESOURCE_LOCAL">
  <provider>org.hibernate.ejb.HibernatePersistence</provider>
  <properties>
   <!-- Connection properties -->
   <property name="hibernate.connection.driver_class" value="org.apache.derby.jdbc.ClientDriver" />
   <property name="hibernate.connection.url" value="jdbc:derby://localhost:1527/c:\derbydb\mydb" />
   <property name="hibernate.connection.username" value="APP" />
   <property name="hibernate.connection.password" value="APP" />

   <property name="hibernate.dialect" value="org.hibernate.dialect.DerbyDialect" />
   <!-- create-drop, create -->
   <property name="hibernate.hbm2ddl.auto" value="update" />
   <property name="hibernate.show_sql" value="true" />
   <property name="hibernate.format_sql" value="true" />
   <property name="hibernate.connection.autocommit" value="true" />
  </properties>
 </persistence-unit>

 <persistence-unit name="eclipseLink-resourceLocal" transaction-type="RESOURCE_LOCAL">
  <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
  <class>com.test.entity.User</class>
  <properties>
   <!-- Connection properties -->
   <property name="eclipselink.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver" />
   <property name="eclipselink.jdbc.url" value="jdbc:derby://localhost:1527/c:\derbydb\mydb" />
   <property name="eclipselink.jdbc.user" value="APP" />
   <property name="eclipselink.jdbc.password" value="APP" />

   <property name="eclipselink.target-database" value="Derby" />
   <!-- drop-and-create-tables -->
   <property name="eclipselink.ddl-generation" value="create-tables" />
   <property name="eclipselink.ddl-generation.output-mode"
    value="database" />
   <property name="eclipselink.logging.parameters" value="true" />
   <property name="eclipselink.logging.level" value="FINE" />
  </properties>
 </persistence-unit>

 <persistence-unit name="openjpa-resourceLocal" transaction-type="RESOURCE_LOCAL">
  <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
  <class>com.test.entity.User</class>
  <properties>
   <!-- Connection properties -->
   <property name="openjpa.ConnectionDriverName" value="org.apache.derby.jdbc.ClientDriver" />
   <property name="openjpa.ConnectionURL" value="jdbc:derby://localhost:1527/c:\derbydb\mydb" />
   <property name="openjpa.ConnectionUserName" value="APP" />
   <property name="openjpa.ConnectionPassword" value="APP" />

   <property name="openjpa.RuntimeUnenhancedClasses" value="supported" />
   <property name="openjpa.jdbc.DBDictionary" value="derby" />
   <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)" />
   <property name="openjpa.Log" value="DefaultLevel=WARN, Runtime=INFO, Tool=INFO, SQL=TRACE" />
  </properties>
 </persistence-unit>
</persistence>

Use Hibernate as JPA provider in Glassfish

Glassfish's default JPA provider is EclipseLink. For some reason, I need to replace EclipseLink with Hibernate as the JPA provider.

This article describes the steps I take, the difficulties I come across and how I overcome them.

My development environment:

Eclipse 3.6.2 (oepe-helios-all-in-one)  downloaded from here.
Glassfish 3.1.2
Apache Derby Server

I begin by creating a ordinary Java project in eclipse, named 'jpa'

Create the persistence.xml file under META-INF folder, which is under src.








Since I am not quite sure whether I have configured the JNDI data source correctly (which is out of the scope of this article), I still use EclipseLink as the JPA provider for now. So here is the contents of persistence.xml.
















Then I create a simple entity bean (User) and a simple stateless session bean (UserManagerBean).

The final project structure should look like this:














I want to test the persistence configuration so eagerly that I immediately create an Enterprise Application Project called jpa-ear, add the jpa project into it, and try to deploy the ear into Glassfish server.

I get the following error unexpectedly. I would expect the console to tell me that the UserManagerBean was successfully deployed and ready to be looked up by JNDI, as such.

I remember having deployed a stateless session bean into JBoss successfully. At this stage, I am not sure whether there is something wrong with my data source configuration or the Glassfish requires a web project to be included in the EAR.



















Then I create a web project, called jpa-web,  and add it to the jpa-ear project. Interestingly, the EAR is deployed successfully even I haven't linked the web project to the ejb project.

The console says UserManagerBean has a JNDI name.






I write a servlet class to make sure the User can be persisted into the database. Now it is time I moved on to the central part of this task ----- replacing the EclipseLink with Hibernete.

I update the persistence.xml to the following:
















As soon as the file is saved, auto deployment kicks off, and an error message pops up.

















Fair enough. That is because Glassfish can't find the hibernate libraries.

I could copy the hibernate libraries into Glassfish's lib folder but I don't want to do that. Because I just want the hibernate persistence provider to be confined in this application scope and don't like the other applications to be affected at all.

So I download the latest hibernate release and add the necessary jar files to jpa project's classpath, only disappointed to see the error is still there.

I copy all the jar files to the lib folder in jpa-web project.  Buy it's still not working.

I then realize that it is the EAR that gets deployed to the server, not the WAR. So if any project needs these jar files, it should be the EAR project rather than the WEB project!

However, there is no lib folder under jpa-ear project. I right click the project, and select Deployment Assembly. There seem to have something I can try.



























I go Add -> Archives from File System -> Add, select all the necessary jar files





























This time it is complaining about another missing class.

















Obviously, the server has found the org.hibernate.ejb.HibernatePersistence class it was complaining about before. Now the org.hibernate.proxy.EntityNotFoundDelegate is missing.

With the help of jarfinder, I come to know that the hibernate-core jar file contains the EntityNotFoundDelegate class. But haven't I just added this class to the EAR project?

Checking out the Deployment Assembly window again, I notice something weird --- The hibernate-core jar file, along with two other jar files, does not have lib in its deploy path.

















Under jpa-web/EAR Libraries, those three jar files without lib in their path are not there!



















I don't know why those 3 jar files are not included in the EAR libraries. Is it a bug of Eclipse?

It looks like I need to change some configuration file to add lib to those 3 jar files' path. Luckily it doesn't take long to find the configuration file. It is named org.eclipse.wst.common.component under jpa-ear/.settings.

For hibernate-commons-annotations.jarjavassist.jarhibernate-core.jar, add lib in their deploy-path attribute. Here is the screenshot for hibernate-core.jar





Refresh the jpa-ear project, redeploy the ear to Glassfish. And it works fine.