Who’s On Phirst

Official blog of Phurnace Software.

Ann Nguyen's Blog
Description:
A short description about your blog

Posted by: Ann Nguyen on

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...


Posted by: Ann Nguyen on

"Mommy, you have to think GREEN"!, my five year old uttered this sentence one day when I picked him up from preschool. At first, I did not comprehend what he had told me and dismissed it as his babbling. Later that evening, while reviewing his take home folder, it dawned on me that preschoolers are now taught the concept of recycling and conservation.

Everyone is recycling these days, the City of Austin has already started the "single stream" recycling program, allowing residents to recycle more items with less hassle. I have a big 90-gallon cart that I can put all my recyclable items in and every day more components are being accepted as recyclable.

The City of Austin/Capital Metro transportation system slogan is "Turn Drive Time Into My Time". I have found that this is no longer a dream. The commute time from Northwest to Downtown Austin is stressful for my daily routine but the city bus transit system is so good now that I have began to use it to get me to and from work. It is wonderful! While sitting on the bus, it is my time. The express bus comes with Wifi and bike racks as well. For the route that I have chosen, using the bus system only costs me 10 to 15 minutes more than if I would have driven myself. They really have made it so convenient that it is hard not to take advantage of it. I also get more exercise in my daily routine while walking to and from the bus route and my office.

If you have glanced at the news lately you cannot help but notice that the Dow Jones Industrial Average has endured its worst weekly loss in its 112 year history. Riding the bus also saves my pocket book - gas is not exactly cheap!

Conserve the environment by riding the bus and save some money! This is a combination that I have to say yes to. I do want to reduce my carbon footprint and want to minimize the cost of cleaning up the environment for the younger generation. The next generation already has to take care of social security for all of us (I honestly do not see how they could do it, there are too many of us and too few of them), much less bear the cost of cleaning up the earth.

(A carbon footprint is the measure of the amount of carbon dioxide -- the major man-made global warming greenhouse gas -- that goes into the atmosphere as you go about your daily life.)

In Untagged 
Comment (0) Read More...


Posted by: Ann Nguyen on

If you have to provided a view that display RSS feeds content within a JSP, you have several choices of how you can approach this.

If you want to roll your own sleeves and parse the RSS XML, you can do so. Another choice is to defined the XML Schema for the different versions of RSS Feed and used JAXP or XMLBeans to generate the parser code for you.

With either one of those above choices, you still have to write the display code using the parser.

Another option, the one that I have chose to used is Sun's RSS Utilities. This comes with both the RSS parser code and a tag library that you could used inside of your jsp page. This utilities support RSS content version 0.91, 0.92, and 2.0.

The RSS Utilities are well documented at:

http://java.sun.com/developer/technicalArticles/javaserverpages/rss_utilities/

http://today.java.net/pub/a/today/2006/03/21/reading-news-with-sun-rss-utilities.html

What I have found out is that the utilities does not handle RSS Feeds with different languages. If you pull down news feeds that are not in English, the characters will not display correctly.

If you are using the same code to display RSS feeds from different places within one application, please be sure to specify the startIndex and endIndex, otherwise, it will only display up to the last index of its previous feed.

<%@ taglib uri="/WEB-INF/tlds/rssutils.tld" prefix="rss" %>
<%@ taglib uri="/WEB-INF/tlds/struts-tiles.tld" prefix="tiles" %>
<%@ page import="com.yourCompany.yourProject.YourConstants"%>
<tiles:useAttribute name="RSS_FeedUrl" scope="request"/>
<rss:feed url="<%=RSS_FeedUrl%>"
feedId="justAnId"/>
<b>Image: </b><rss:channelImage feedId="justAnId"/>
<b>Title: </b><rss:channelTitle feedId="justAnId"/>
<b>Link: </b><rss:channelLink feedId="justAnId" asLink="true"/>
<b>Description: </b><rss:channelDescription feedId="justAnId"/>
<ul>
<rss:forEachItem feedId="justAnId" startIndex="0" endIndex="<%=YourConstants.MAXIMUM_RSS_ITEMS%>">
<a href="<rss:itemLink feedId="justAnId"/>" target="_new"><rss:itemTitle feedId="justAnId"/></a>
<rss:itemDescription feedId="justAnId"/>
</rss:forEachItem>
</ul>

 

If the RSS tag could not parse, it will just throws Exception, thus it would be wise to catch these exception and handle it appropriately for your application, or for your portlet.

Happy RSSing and if you find an easy tool that could handle I18N, please let me know.

In Untagged 
Comment (0) Read More...