Featured Post

The great debacle of healthcare.gov

This is the first time in history when the president of the United States of America, or probably for any head of state around the world,...

Wednesday, November 14, 2007

Datasource scope issue in j2ee application

Before jump into the issue, lets discuss how JNDI naming works.

The JNDI lookup for any resources is resolved relative to the context defined in the Initial Context (which can be created from various jndi api like InitialContext, InitialLdapContext etc.). The exception happens only if the URL string is specified to lookup any resources (which i. URL format is defined as:
scheme_id:scheme-specific-part

J2EE specification implementation provides a root URL context as java: which is made available by any vendor container supporting J2EE specification. At the root context of the namespace, 'comp' is bounded for the components like ejb, servlet and jsp. And the 'env' is bounded to the 'comp' namespace and provided to component by the container. Usually the component deployment descriptor (e.g. web.xml for servlet/jsp component) defines the requires resource references in the descriptor and are available through java:comp/env namespace.

To understand the issue more clearly, we also need to understand the scope of the jndi lookup. There are two scopes in which any resources are looking up:

i. Component scope: This scope is resolved using the 'java:comp/env' text before the jndi resource name

ii. Server scope: This scope is resolved just by using the resource jndi name.

Now come to the point. Below is the xml tag of web application configuration file.
<resource-ref id="ResourceRef_121212121" >

<description>TestDataSource</description>

<res-ref-name>jdbc/TestDataSource</res-ref-name>

<res-type<javax.sql.DataSource</res-type>

<res-auth>Container</res-auth>

</resource-ref>

In the web.xml file of web application, the above tag creates the reference of resources. The child tag declares the name for the container bound resource so that the servlet in the web application can get the resource within the component scope (java:comp/env/). If the datasource were not declared in the web.xml then the datasource couldn't be found in the java:comp/env namespace. Though the resource bound in the application server can be found in the using the JNDI name directly, but it is not portable because the JNDI binding name could be changed anytime by the Application Server administrator.


In Tomcat, the datasource can be found in the component scope without refering the datasource in the web.xml, most probably, becuase the web component is the only component that can be deployed within it. But WebSphere Application Server (WAS) restricts access to resources those are not referenced in the web.xml. Whereas, in RAD-TestEnvironment (WAS 5.1 Test Environment), the datasource can be found with lookup using the JNDI name directly (the jndi name itself) but in WAS it doesn't work. That means inorder to access datasource from web component in WAS, the lookup name must be in component scope i.e. java:comp/env scope and the resource must be referenced in web.xml, the web component deployment descriptor

Resources
http://java.sun.com/products/jndi/tutorial/beyond/misc/policy.html
http://java.sun.com/products/jndi/tutorial/beyond/url/initctx.html
http://javahowto.blogspot.com/2006/07/when-and-where-not-to-use-javacompenv.html
http://forum.springframework.org/showthread.php?t=17712
http://www.theserverside.com/discussions/thread.tss?thread_id=27675
http://forum.java.sun.com/thread.jspa?threadID=568055&messageID=2807207
http://stackoverflow.com/questions/7167212/how-do-i-connect-to-a-websphere-datasource-with-a-given-jndi-name

Tuesday, November 13, 2007

Implement Spring in a Struts project

The implementation of Spring framework in a matured project could be tricky. Following step by step progressive integration could help to ease some of the pains:

- To prepare a project for Spring, first of all, we've to ensure that Inversion of Control Design concept is followed through out the application. And for that preparation the team might need to undergo thorough refactoring and/or redesigning, depending on the existing implementation and design.

- Write or re-write the business logic and data logic (DAO) classes with DI pattern. Create the Spring context XML file for the business and DAO classes. Inject the business logic objects into the Action classes using any Spring Context.

- After refactoring the existing code enabling Dependency Injection, second step is to prepare the Struts action classes to integrate with Spring. In this case the same DI needs to be enabled in the Action classes. The Action class shouldn't be burdened with redundant logic codes other than controlling logics. Use the Delegation Proxy to create the Struts Action classes through Spring. Before that ensure that the injection of

- Remove all logging cross-cut codes from the classes and use Spring Interceptor (BeforeMethod advice) and implement the logging

- To manage the application's transaction using Spring declarative transaction, implement it through proxy. The transaction declaration needs more time to analyze rather than implement. Do the homework on transaction grouping and then implement it in the xml file. Rigorously testing requires to confirm functional and performance requirements.

Struts-Spring Integration Using Proxy

DelegatingActionProxy is the object that plays the role to create Struts Action class when the request is invoked.

1. Modify your struts-config.xml file to give the DelegatingActionProxy to play its role

path="/someAction" name="someForm"
type="org.springframework.web.struts.DelegatingActionProxy"
input="/someOtherAction.do">


2. Add an entry for the path, in this case, '/someAction' in the spring configuration




Open View in transaction in Spring with Hibernate

1. Create a Filter to handle the transaction:


AppFilter</filter-name>
Application Transaction Filter

org.springframework.web.filter.DelegatingFilterProxy



2. Set the Filter to accept any request ends with .d0

AppFilter
*.


3. Set the Listener that loads Spring's WebAppContext


org.springframework.web.context.ContextLoader


4. set the parameter value of the configuration file that configures the Transaction Filter and Transaction Manager


contextConfigLocation

/WEB-INF/WebContext.xml



5. Configure the Filter










6. Implement the Filter class

DefaultTransactionDefinition def = new DefaultTransactionDefinition();

if (!TransactionSynchronizationManager.hasResource(sessionFactory)) {
session = SessionFactoryUtils.getSession(sessionFactory, true);
TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
}

status = transManager.getTransaction(def);
chain.doFilter(req, res);

//commit
getTransactionManager().commit(status);
//rollback
getTransactionManager().rollback(status);

//Close the Session
TransactionSynchronizationManager.unbindResource(sessionFactory);
SessionFactoryUtils.closeSession(session);


Resources:

http://springtips.blogspot.com/ - Spring tips
Spring-Struts integration - Spring integration with Struts Action
Spring transaction blog - A compact discussion of spring transaction implementation

Useful RAD keyboard shortcuts

I used Rational Application Developer (RAD 7.0) to test the below keyboard shortcuts. All of the shortcuts are for the Java/J2EE perspectives:

Editor

Ctrl+M -> Maximize/Minimize the current editor

Ctrl+W -> Close the current editor

Ctrl+E -> Show all editor

Ctrl+D -> Delete line from cursor position

Ctrl+T -> Open the Type, if on method or class then shows the available subtypes

Cntrl+O -> Open the members

Ctrl+Shift+F6 -> Show available Editors

Ctrl+Shift+F7 -> Show available views (need to check)

Ctrl+Shift+F8 -> Show available perspectives (need to check)

Alt+ Arrow keys -> move forward/backword to the last change position

F12 -> Activate the editor

F3 -> Open the declaration

Cntrl+Shift+M -> Add import statement for the Class used in the code (shows error as underline red
                            for the class used but not imported the class i.e. import statement isn't written
Cntrl+Shift+O -> Organize the import statements i.e. if you've removed some classes from your
                            code but the important statement wasn't deleted this command will clean up those
                            unused  import statements

Cntrl + F4 -> to close the currently active tab on the Editor


Search

Cntrl+Shift+R -> Search for Resources

Cntrl+Shift+T -> Search for Types

Cntrl+K -> Go to the next search result

Cntrl+Alt+H -> Show the call hierarchy of a method (highlight on the method you want to see the call trace)

Cntrl+Shift+H -> To search for Java Classes (Type)


Code structure change


Alt+Shift+R -> Rename (refactor) of class/member


Note: To change the keyboard shortcut mapping, go to Windows -> Preferences -> Workbench -> Keys