In the world of fast paced development, you are usually tasked to deliver some features in a very short turnaround time. Does this sound familiar to you? Especially if you are in an IT shop, you find yourself more and more like an assembler, you just integrate and connect software together for the final product, and you have to rely on tools of the 21st century.
I was given, or rather volunteered, to pull data from one web application to display on a client’s web application remotely. The web application that provided the necessary data used EJB for all its CRUD operations. Instead of reinventing the wheel, I added more methods to the stateless session bean to expose the data that I needed.
First step, with EJB 2.1: Axis is the best tool for this that I have found. Axis is packaged as another web module into your application and exposes the EJB methods as a Web Service.
The Axis server-config.wsdd needs to define the Web Service.
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<service name="AdminService" provider="java:MSG">
<parameter name="allowedMethods" value="AdminService"/>
<parameter name="enableRemoteAdmin" value="false"/>
<parameter name="className" value="org.apache.axis.utils.Admin"/>
<namespace>http://xml.apache.org/axis/wsdd/</namespace>
<namespace>http://xml.apache.org/axis/wsdd/</namespace>
</service>
<service name="Version" provider="java:RPC">
<parameter name="allowedMethods" value="getVersion"/>
<parameter name="className" value="org.apache.axis.Version"/>
</service>
<service name="Verify" provider="java:RPC">
<parameter name="allowedMethods" value="getAxisVerification"/>
<parameter name="className" value="com.mycompany.dataserver.model.session.DataEJBService"/>
</service>
<handler name="URLMapper" type="java:org.apache.axis.handlers.http.URLMapper"/>
<transport name="http">
<requestFlow>
<handler type="URLMapper"/>
</requestFlow>
</transport>
<service name="DataByPersonId" provider="java:EJB">
<parameter name="scope" value="application"/>
<parameter name="beanJndiName" value="java:comp/env/DataEJB"/>
<parameter name="homeInterfaceName" value="com.mycompany.dataserver.model.session.DataEJBLocal"/>
<parameter name="remoteInterfaceName" value="com.mycompany.dataserver.model.session.DataEJBLocal"/>
<parameter name="allowedMethods" value="getDataByPersonId,getDataByOrgId,getDataIDsByOrgId"/>
<parameter name="className" value="com.mycompany.dataserver.model.session.DataEJBBean"/>
<beanMapping xmlns:ns="urn:DataByPersonId.session.model.dataserver.mycompany.com" qname="ns:DataWsDTO"
languageSpecificType="java:com.mycompany.dataserver.model.datatransferobject.DataWsDTO"/>
</service>
</deployment>
Since the EJB did not support the remote interface, the web.xml for the Axis servlet needs to define the reference to the session bean.
<ejb-local-ref>
<ejb-ref-name>DataEJB</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local>com.mycompany.dataserver.model.session.DataEJBLocal</local>
<ejb-link>ListingsEJB</ejb-link>
</ejb-local-ref>
First step, with EJB 3: Life is much easier with EJB 3. One just has to use some dependency injection keywords.
The DataEJBBean file:
@WebService(endpointInterface="com.mycompany.dataserver.model.session.DataEJBRemote",targetNamespace="...")
@Stateless(name="DataEJB")
@Remote(DataEJBRemote.class)
@TransactionManagement(TransactionManagementType.CONTAINER)
@Resource(name="jdbc/MyCompanyDataServerDS", type=javax.sql.DataSource.class)
@Deployment(contextPath="data-ejb")
public class DataEJBBean implements DataEJBLocal, DataEJBRemote {
@WebMethod(operationName="featuredData")
@TransactionAttribute (TransactionAttributeType.SUPPORTS)
public DataWsDTO[] getDataByPersonId(Integer personId) {
.
.
.
}
@WebMethod(operationName="featuredData")
@TransactionAttribute (TransactionAttributeType.SUPPORTS)
public String getDataIDsByOrgId(Integer orgId) {
.
.
.
}
@WebMethod(operationName="featuredData")
@TransactionAttribute (TransactionAttributeType.SUPPORTS)
public ListingWsDTO[] getDataByOrgId(Integer orgId) {
.
.
.
}
.
.
.
}
The DataEJBRemote file:
@WebService
public interface DataEJBRemote extends Remote {
@WebMethod
public DataWsDTO[] getDataByPersonId(Integer personId) throws java.rmi.RemoteException;
@WebMethod
public String getDataIDsByOrgId(Integer orgId) throws java.rmi.RemoteException;
@WebMethod
public DataWsDTO[] getDataByOrgId(Integer orgId) throws java.rmi.RemoteException;
}
For EJB 3 at this stage of the game, I would support the remote interface, especially for the Web Services features.
We are all familiar with the software life cycle story, the PM for that container release probably only schedules mainstream use cases into these earlier releases. If you like pain, and you do have the time, you can venture out more.
Second Step, obtaining the WSDL for the Web Service: If you use Axis, you can use the ant task Java2WSDL to obtain the WSDL. You can also invoke the URL of your web service with "?wsdl" at the end to obtain the WSDL.
Third Step, generate the client stubs for the web service consumer: I used Axis for this and generated the client stubs from the WSDL obtained in the second step. The client stubs will need to be package into the consumer web applications.
If you are like me, we all have to support the different staging steps: development, QA, and production. Each of the machines for these are different for both the server and the consumers and we only want to move the same ear through these steps of staging.
In the ...SoapBindingStub.java file that is generated by Axis, I modified the static method to pull the Web Service namespace from a properties file. The property file for development, QA, and production will need to reflect its environments.
public static String getDataWebServiceNamespace() {
return FileUtils.getDataWebServiceUrl();
}
Everywhere that the Web Service namespace is needed, use this method to obtain it.
Fourth Step, deployment night: Deployment night is scheduled late in the evening. Most IT shops do this. After all of the work, the frustration, the hair pulling and frantic reading into Open Source documentation like Axis (we all just LOVE Open Source documentation...), it DID NOT work in the production environment.
So you are now troubleshooting late into the night and the whole deployment team is weary and tempers flare easily.
The deployment system admin person did not move the correct property file into the production environment. Well, it is not their fault totally, you did not spell out exactly what files need to move to where clear enough in the manual deployment instructions.
This is why you need to look into Phurnace Deliver, especially the upload file functionality. It will save you so much time - your time, not machine time, from erroneous manual mistakes.
In Untagged
Comment (0)
Read More...