This article brings together Spring and XFire configuration examples to show how to expose simple POJO into SOAP service with EJB façade in between.
Lets take a simple example of number add and subtract service.
Here is component diagram of what we are trying to achieve.
To accomplish the above setup we’ll follow these simple steps.
Create NumberService interface and implementation.
public interface NumberService{
public int add(int n1, int n2);
public int substract(int n1, int n2);
}
public class NumberServiceImpl implements NumberService{
public int add(int n1, int n2){
return n1 + n2;
}
public int substract(int n1, int n2){
return n1 - n2;
}
}
Create app-context.xml (you can name this file anything you want).
Since we are using Spring Framework it just makes sense to define the NumberServiceImpl in spring context file to be later injected into NumberServiceSessionBean. This will allow us to decouple
NumberServiceSessionBean from NumberServiceImpl. Here is the full context file called app-context.
Make sure this file is in classpath for EJB to load.
Create NumberServiceSessionBean
import java.rmi.RemoteException;
import javax.ejb.CreateException;
import org.springframework.ejb.support.AbstractStatelessSessionBean;
public class NumberServiceSessionBean extends AbstractStatelessSessionBean{
private NumberService numberService = null;
protected void onEjbCreate() throws CreateException{
numberService = (NumberService)getBeanFactory().getBean("numberService");
}
public int add(int n1, int n2) throws RemoteException {
return numberService.add(n1, n2);
}
public int substract(int n1, int n2) throws RemoteException {
return numberService.substract(n1, n2);
}
}
Here are few things worth to mention.
-
It extends Spring helper AbstractStatelessSessionBean class which will load spring context behind the scene and expose it through
BeanFactory getBeanFactory() method.
Some might ask how it knows which context file to load? Well in order to tell the AbstractStatelessSessionBean the location of context file we need to define it in EJB deployment (called ejb-jar.xml ) file like this.
ejb/BeanFactoryPath java.lang.String - Each NumberServiceSessionBean instance will load context file separately and will have its own instance of NumberServiceImpl.
- It does not directly implement NumberService but implements the exact methods. The reason behind this is two-part. First it is the infamous issues of the need to declare RemoteException in NumberService. Second one will be explainined later when we expose it as proxy to Xfire servlet.
Create XFire web component.
For XFire to be able to receive SOAP calls we need to configure it as Servlet.
What we are going to do is again leverage Spring Framework by reusing its org.springframework.web.servlet.DispatcherServlet and expose XFire to it as Spring MVC controller.
The good news is that XFire already provides implementation of this controller in “org.codehaus.xfire.spring.remoting.XFireExporter” class.
To have complete web application we need to create web.xml and Spring nameservice-context.xml file that will contain Controller and EJB proxy definitions.
Put both under WEB-INF directory.
web.xml
nameservice
org.springframework.web.servlet.DispatcherServlet
1
nameservice
/*
Once deployed and loaded in Servlet container DispatcherServlet will assume there is Spring context file under WEB-INF directory with name {servlet-name}-servlet.xml
which is in our case nameservice-servlet.xml.
nameservice-servlet.xml
NameServiceSessionHome
weblogic.jndi.WLInitialContextFactory
false
false
NameService
rpc
encoded
NameService
Finally to test your WebService invoke http://localhost:7001/nameservice?wsdl which will generate the WSDL.
Included with the war project is JUnit test that uses Spring and XFireClientFactoryBean to remotely call XFire service using Spring and XFire proxies. For more detailed tutorial
on XFireClientFactoryBean check http://xfire.codehaus.org/Spring+Remoting.
The unit test requires “commons http client” libraries, so make sure to include them as dependencies in your war as is done in attached maven projects.
Full maven project can be downloaded from HERE.
Build Instructions
- This project is based on Maven2. Currently standard Maven2 remote repositories dont have xfire-all-1.2.2.jar. You might need to manually get it from here and put into your local repository under xfirexfire-all1.2 directory.
- If you are going to deploy it to Weblogic it wont work unless resolve QName issue as shown here.
Tsolak,
Thanks a lot for your guide and diagram – it does help make things clear a bit.
I hope you don’t mind a few quesstions from a newbie to xfire/spring:
– Does one have to use rpc/encoded or can one use
doc/literal with the above scenario?
Yes multiple styles/encodes are supported. For style you can use the following values “document|rpc|message|wrapped” and “literal|encoded” for use property.
Here is the link to full reference.
Tsolak,
I did successfully deployed to weblogic 8.1.4. I modified the ejb pom (see below). But my problem is that I can not get wsdl to be displayed at http://localhost:7001/numberservice-ear-1.0.0/numberservice?wsdl
(my ear name is numberservice-ear-1.0.0.ear)
ejb pom.xml
————–
4.0.0
numberservice-ejb
ejb
1.0.0
EJB Facade for NumberService
EJB Facade for NumberService.
samples
samples
1.0.0
maven-antrun-plugin
package
************** RUNNING WEBLOGIC EJBC ****************
run
ant
ant-antlr
1.6.5
commons-logging
commons-logging
1.0.4
jar
org.springframework
spring-core
1.2.8
jar
org.springframework
spring-aop
1.2.8
jar
org.springframework
spring-beans
1.2.8
jar
org.springframework
spring-context
1.2.8
jar
org.springframework
spring-remoting
1.2.8
jar
javax.ejb
ejb
2.1
provided
${pom.groupId}
1.0.0
numberservice-jar
jar
I found this blog/article on the Articles list in the XFire documentation. I need to expose an EJB’s method as a Web Service BUT we do not use Spring. Our application is a server with Swing clients started thru WebStart.
How would I modify what you have documented here in order to expose my EJB as a web service from XFire?
You can bypass Spring config file and manually create spring beans, proxies and servlet.
Or hopefully this article might help you:
http://xfire.codehaus.org/Invokers
Is there a chance this article can be re-written but using the CXF stack?
I probably can. Might be in a few weeks.
Here is how to do with CXF.
[…] Full maven project can be downloaded from HERE. This is a follow up article to XFIRE+EJB+POJO. Here I show how to expose POJO using CXF project instead of XFire. Setting up WebServices with CXF is very easy and consists of two steps: […]