PDA

View Full Version : EJB to Spring Migration


kasim
May 22nd, 2007, 01:20 AM
Hi

I have an existing application which runs on EJB, now i need to migrate to Spring 2.x.
M application is working fine with migration of Spring by using ClassPathXmlApplicationContext.
Now i need to run the same thing without using ClassPathXmlApplicationContext since this is used for Standalone application.
In web.xml file i have specified the listener as

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/ApplicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListe ner</listener-class>
</listener>




Here i have placed my ApplicationContext.xml in WEB-INF/classes;
1) if i place ApplicationContext.xml in WEB-INF and call the factory as
ApplicationContext factory = new ClassPathXmlApplicationContext("WEB-INF/ApplicationContext.xml");
it says file doesnt exist, why?
if i put the file in classes and call as new ClassPathXmlApplicationContext("/ApplicationContext.xml"); it works fine

Search search;

ApplicationContext factory = new ClassPathXmlApplicationContext("/ApplicationContext.xml");
//XmlBeanFactory factory = new XmlBeanFactory(resource);
search = (Search) factory.getBean("saveSearch");
search.saveSearchCriteria(aRequestObject);


2) now i dont want to use ClassPathXmlApplicationContext, i need to get directly through spring container. I am using an interface to call the bean.
as

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
<bean name="saveSearch" class="com.standardandpoors.apps.cdoonline.ejb.search.Sea rchManagerService">
<!--<property name="search">
<ref bean="com.standardandpoors.apps.cdoonline.ejb.search.Sea rchManagerService"/>
</property> -->
</bean>
<bean name="searchInt" class="com.standardandpoors.apps.cdoonline.ejb.search.Sea rchManagerService">
</bean>
</beans>


this how my code should look like:
//ApplicationContext factory = new ClassPathXmlApplicationContext("/ApplicationContext.xml");
//XmlBeanFactory factory = new XmlBeanFactory(resource);
//search = (Search) factory.getBean("saveSearch");
search.saveSearchCriteria(aRequestObject);

how can i mygrate without loading ClassPathXmlApplicationContext? i am getting null pointer exception why?


regards
Kasim

Marten Deinum
May 22nd, 2007, 03:41 AM
Have you read the Spring Reference guide and have taken a look at the samples shipped with Spring? Try to get a grasp at what dependency injection is/does for you.

Simply inject all of your references into the bean which needs them, instead of looking them up.

kasim
May 22nd, 2007, 05:56 AM
thanks for your reply,

I have tried it, my ApplicationContext.xml file is:

<beans>
<bean name="saveSearch" class="com.st.apps.cdoonline.common.servicehandler.Search ServiceHandler">
<property name="search">
<ref bean="saveSearch"/>
</property>
</bean>
<bean name="saveSearch" class="com.st.apps.cdoonline.ejb.search.SearchManagerServ ice">
</bean>
</beans>


and my Bean calling code is:

public ResponseObject saveSearchCriteria(RequestObject aRequestObject)
throws BusinessException
{
search.saveSearchCriteria(aRequestObject);
}

public void setSearch(Search search) {
this.search = search;
}

Here SearchManagerService implements Search.
still it throws nullpointer exception. why?

Marten Deinum
May 22nd, 2007, 06:08 AM
Well you are overriding your bean in your context, you have 2 beans with the same name, so only one will be available to your context.


<beans>
<bean name="saveSearch" class="com.standardandpoors.apps.cdoonline.common.service handler.SearchServiceHandler">
<property name="search" ref="saveSearch"/>
</bean>
<bean name="saveSearch" class="com.standardandpoors.apps.cdoonline.ejb.search.Sea rchManagerService" />
</beans>


Same name.

Solution should be obvious....

kasim
May 22nd, 2007, 07:29 AM
I have changed the file as


<bean name="searchHandler" class="com.st.apps.cdoonline.common.servicehandler.Search ServiceHandler">
<property name="search">
<ref bean="saveSearch"/>
</property>
</bean>

<bean name="saveSearch" class="com.st.apps.cdoonline.ejb.search.SearchManagerServ ice">
</bean>

still it throws null pointer exception. why?

Marten Deinum
May 22nd, 2007, 07:36 AM
How do you receive a reference to your searchHandler? Are you injecting it into another bean or are you creating one with new yourself?

kasim
May 22nd, 2007, 07:45 AM
For calling SearchServiceHandler ie searchHandler, i am calling with new from the action class. (or action class uses an interface and implemented in this handler.) from action class i am getting ref of Handler thro interface.

Marten Deinum
May 22nd, 2007, 08:18 AM
Which is where your problem lies. You are creating an instance of the bean outside of the Spring container. You should inject the reference to the handler in the action bean also, or look it up from the context (which you can access by using the WebApplicationUtils).

kasim
May 22nd, 2007, 09:26 AM
Oh, thats great Marten Deinum, I will try it out and inform you. What i need to do here is specify all the objects/classes and inject references.
now i need to put my ApplicationContext.xml file in WEB-INF file. at present i am keeping in WEB-INF/classes and calling it as = new ClassPathXmlApplicationContext("/ApplicationContext.xml"); it works fine, but when i keep in WEB-INF/ApplicationContext.xml and call as new ClassPathXmlApplicationContext("WEB-INF/ApplicationContext.xml"); it says file ApplicationContext.xml doesnt exist

Marten Deinum
May 22nd, 2007, 09:39 AM
You don't want to create a new ApplicationContext each time. That is why you specified the ContextLoaderListener, this will create and instantiate the ApplicationContext for you.

Place the file applicationContext.xml inside your WEB-INF folder and use the ContextLoaderLister to initialize your context.

In your class do something like


ApplicationContext ctc = WebApplicationContextUtils.getWebApplicationContex t(servletcontext);


or when only having a HttpServletRequest at your disposal


ApplicationContext ctx = RequestContextUtils.getWebApplicationContext(reque st);


However to give a more detailed answer we would need to see the code (and the code that is calling) of your action.

kasim
May 22nd, 2007, 09:57 AM
my Action class looks like this:

public class ActionSearchDeal extends Action{
.....
execute(){
.....
....
ServiceHandlerFactory mServiceHandlerFactory = ServiceHandlerFactory.getFactory();
IServiceHandler mServiceHandler = mServiceHandlerFactory.getServiceHandler(Constant. SEARCH_SERVICEHANDLER);
mServiceHandler.execute(mRequestObject);
}



Here execute is implemented in SearcServiceHandler.

karldmoore
May 22nd, 2007, 01:20 PM
If you follow this article there are several examples of how to wire Spring and Struts together.
http://www-128.ibm.com/developerworks/java/library/j-sr2.html

kasim
May 23rd, 2007, 02:14 AM
this link doesnt help me, since it couples spring with struts. i dont want use spring in struts, my problem is to inject the values here for migration.

Marten Deinum
May 23rd, 2007, 02:32 AM
How is your application structured? Where do these actions come from? How do you create these actions? If you want a reference to your other object simply inject them (and make your action beans also spring managed beans) into your beans.

Did this thread (http://forum.springframework.org/showthread.php?t=39062) solve your problem? As it appears you are using Struts?

kasim
May 23rd, 2007, 03:00 AM
My existing application uses Struts framework. It just calls execute() method as usual and i have the part of action class above thread. Now i have changed to ActionSupport from action and added the plugins in struts-config.xml file. added a new xml file for ref this.

For injecting other beans i have a problem here:

since my existing application uses a factory as shown above, what i need to do here? shall i remove the calling factory and getServiceHandler? just set a setter method in action class and inject values?

kasim
May 23rd, 2007, 08:25 AM
my ServiceHandler Factory class is:


public class ServiceHandlerFactory
implements java.io.Serializable
{

private static ServiceHandlerFactory oServiceHandlerFactory = null;
private static Hashtable oActionHashtable = new Hashtable(); // (key =action key, value = Array List of ServiceHandler).

ArrayList oServiceHandler = new ArrayList();

/**
* Method getServiceHandler - This method will instantiate the service handler depending upon
* the action key passed to it and will return the instance.
* @param String aServiceHanlderKeyString
* @return IServiceHandler
* @throws BusinessException
*/
public IServiceHandler getServiceHandler(String aServiceHanlderKeyString) throws BusinessException
{
IServiceHandler mServiceHandler = (IServiceHandler) oActionHashtable.get(aServiceHanlderKeyString);
return mServiceHandler;
}

/**
* Method getFactory - This method returns the instance of <code>ServiceHandlerFactory<code> if
* it is available or make a new one and return it.
* @return ServiceHandlerFactory - Returns the oServiceHandlerFactory
* @exception Exception aException
*/
public synchronized static ServiceHandlerFactory getFactory() throws BusinessException
{
try {
//Check if the instance of exists.
if (oServiceHandlerFactory == null) {
oServiceHandlerFactory = new ServiceHandlerFactory();
}
return oServiceHandlerFactory;
}
catch (Exception aException) {
throw new BusinessException();
}
}

/**
* Method buildServiceHandler - adds the service handler
* @param String aServiceHandler
* @param IServiceHandler aServiceHandler
* @return void
*/
public void buildServiceHandler(String aActionKeyString, IServiceHandler aServiceHandler)
{
IServiceHandler mServiceHandler = (IServiceHandler) oActionHashtable.get(aActionKeyString);
if (mServiceHandler == null) {
oActionHashtable.put(aActionKeyString, aServiceHandler);
}
}

}




I am calling this factory in the Action class as:


ServiceHandlerFactory mServiceHandlerFactory = ServiceHandlerFactory.getFactory();
IServiceHandler mIServiceHandler = mServiceHandlerFactory.getServiceHandler("deals");
return mIServiceHandler.execute(aRequestObject);


Now i need to inject the values in the ApplicationContext.xml file, and finaly code shouldnot use the factory(if i am not wrong), and the code should look as

....
return this.serviceHandler.execute(aRequestData);

public void setIServiceHandler(IServiceHandler serviceHandler) {
this.serviceHandler = serviceHandler;
}


here i need to pass the parameter for getServiceHandler and also need to inject the get factory. Since if i say in (ApplicationContext.xml file)
<properties name="serviceHandler" corresponding setServiceHandler() need to be there, but i dont have that method and dont want create that method, since it is a factory pattern. also need to inject to getFactory to get initiate service handler.

How to solve this?

kasim
May 24th, 2007, 01:27 AM
Now i have removed the factory lookup. I have just injecting the values in Applicationcontext.xml file in, but still i am getting nullpointer excception when i try to inject the values in ApplicationContext.xml file. If i do

ApplicationContext factory = new ClassPathXmlApplicationContext("/ApplicationContext.xml");
serviceHandler = (IServiceHandler) factory.getBean("searchServiceHandler");
mResponseObject = this.serviceHandler.execute(aRequestObject);
}

public void setServiceHandler(IServiceHandler serviceHandler) {
this.serviceHandler = serviceHandler;
}


ApplicationContext.xml file is:

<bean name="searchServiceHandler" class="com.ss.apps.online.common.servicehandler.SearchSer viceHandler">
<property name="search">
<ref bean="saveSearch"/>
</property>
</bean>

<bean name="saveSearch" class="com.ss.apps.online.ejb.search.SearchManagerService">
</bean>

</beans>


How can i avoid the hard coding of classpathresource? since i am injecting the action class (as shown above) service handler and my service(old EJB) in ApplicationContext.xml. why still it throws null pointer exception? some thing goes out of spring container? which is out of the spring container?

Marten Deinum
May 24th, 2007, 02:33 AM
If you are using struts and use the normal Spring integration for Struts you can simply let the context inject it. Have you read the manual chapter 15.4 (http://static.springframework.org/spring/docs/2.0.x/reference/webintegration.html#struts) and the samples shipped with Spring? The petstore provides a struts implementation which uses Spring and injection.


Now i have changed to ActionSupport from action and added the plugins in struts-config.xml file. added a new xml file for ref this.


In a ActionSupport bean there is a method calleg getWebApplicationContext which will give you the ApplicationContext initialized at startup.

However you state that y ou have configured the desired plugins and created the desired (extra) xml files. In these xml files you can configure your beans, as mentioned in chapter 15.4.1 (http://static.springframework.org/spring/docs/2.0.x/reference/webintegration.html#struts-contextloaderplugin).

kasim
May 24th, 2007, 03:30 AM
as you said i have made the changes and working fine,


WebApplicationContext ctx = getWebApplicationContext();
serviceHandler = (IServiceHandler) ctx.getBean("searchServiceHandler");



this is fine when i use it in my Action class. what about in other classes ? eg: Servicehandler and ManagerService(which was earlier my EJB) how do i get the ref there from XML file? if i inject directly it throws nullpointer exception.

kasim
May 25th, 2007, 02:29 AM
any idea why i am getting nullpointer exception?

Marten Deinum
May 25th, 2007, 02:55 AM
Probably because your integration isn't complete correct. Can you post your configuration files?

kasim
May 26th, 2007, 02:38 AM
Probably because your integration isn't complete correct. Can you post your configuration files?

i have given my Applicationcontext.xml file in the above post#17.

kasim
May 28th, 2007, 05:59 AM
Probably because your integration isn't complete correct. Can you post your configuration files?



<bean name="searchServiceHandler" class="com.ss.apps.online.common.servicehandler.SearchSer viceHandler">
<property name="search">
<ref bean="saveSearch"/>
</property>
</bean>

<bean name="saveSearch" class="com.ss.apps.online.ejb.search.SearchManagerService">
</bean>

</beans>

kasim
May 29th, 2007, 11:04 AM
i have given my config file and all other java files in the previous post, still it throws nullpointer exception, why?

i am calling my SearchServiceManager class(earlier EJB) in SerarchServiceHandler, setting a value in SerarchServiceHandler and passing parameter as search which is an interface implemented in SearchServiceManager


public class SearchServiceHandler{
private Search search;
........
public ResponseObject saveSearchCriteria(RequestObject aRequestObject)
throws BusinessException
{
ResponseObject mResponseObject = null;
print("Inside SaveSearchServiceHandler:saveSearchCriteria");
try {

//ApplicationContext factory = new ClassPathXmlApplicationContext("/ApplicationContext.xml");
//XmlBeanFactory factory = new XmlBeanFactory(resource);
//search = (Search) factory.getBean("saveSearch");
search.saveSearchCriteria(aRequestObject);

} catch (Exception e) {
print("Exception:" + e.toString());
}
}
public void setSearch(Search search) {
this.search = search;
}
}

kasim
May 30th, 2007, 05:58 AM
I need to pass interface as parameter in a method as: public void setSearch(Search search) {
this.search = search;
}

Now, in ApplicationContext.xml file i have specified ref bean as:

<property name="search">
<ref bean="com.ss.apps.cdoonline.ejb.search.Search"/>
</property>

but when i run it throws exception why?

.
weblogic.management.DeploymentException:
Exception:weblogic.management.ApplicationException : start() failed.
Module: CdoOnlineWeb Error: weblogic.management.DeploymentException: Error creating bean with name 'searchServiceHandler' defined in S
ervletContext resource [/WEB-INF/ApplicationContext.xml]: Cannot resolve reference to bean 'com.ss.apps.cdoonline.ejb.search.Search
' while setting bean property 'search'; nested exception is org.springframework.beans.factory.NoSuchBeanDefini tionException: No bean named 'com.ss.apps.cdoonline.ejb.search.Search' is defined - with nested exception:
[org.springframework.beans.factory.NoSuchBeanDefini tionException: No bean named 'com.ss.apps.cdoonline.ejb.search.Search' is define
d]

can't we pass interface as an argument in spring?

Marten Deinum
May 30th, 2007, 06:09 AM
Well what does the exception say? There is no bean with the name 'com.ss.apps.cdoonline.ejb.search.Search'. You are referencing a bean which doesn't exist. What you want is


<property name="search">
<bean="com.ss.apps.cdoonline.ejb.search.Search"/>
</property>

kasim
May 30th, 2007, 06:12 AM
i have bean ie my interface 'Search' in that location, why it is not considerining? but if i specify a class instead of interface it is taking it....
<bean="com.ss.apps.cdoonline.ejb.search.Search"/>
is it a correct way of deining a bean?

Marten Deinum
May 30th, 2007, 06:21 AM
Because it is the NAME of the bean not the location of the Class.

I strongly suggest you read the reference guide and try to get a grasp of Dependency Injection and Inversion of Control. You have multiple post on the forum in which you seem to be battling against/with these principals.