Showing posts with label java. Show all posts
Showing posts with label java. Show all posts
2008-01-28
SlimFIX gets new life
I just found that a project I developed a few years back SlimFIX has been adopted by an open source project called ActiveQuant. I am glad it finally gets a new life.
2006-05-23
JBoss application configuration during deployment time
I was looking for a mechanism to configure my application during deployment time. We have our own configuration module but it does not handle the case for deployment descriptor. For example, the application needs to connect to different JMS queues in different environment. The JMS queue name is usually specified in the jboss.xml which is wrapped in the ear file. Our old approach is to use an Ant script build the ear file during the deployment time. It is tedious and also makes it difficult to see what is actually configured. Now I discovered a new way to do it. I can actually use ${param_name} inside the jboss.xml and use JBoss's system property service to define the actual value of the parameter in a seperate property-service.xml. By doing that, I can have the ear file created during the build time and deploy it along with an environment specific property file. It works just wonderful.
To know how it is done, you can take a look at org.jboss.metadata.MetaData.java. And here is the documentation from the Javadoc:
Go through the input string and replace any occurance of ${p} with the System.getProperty(p) value. If there is no such property p defined, then the ${p} reference will remain unchanged. If the property reference is of the form ${p:v} and there is no such property p, then the default value v will be returned. If the property reference is of the form ${p1,p2} or ${p1,p2:v} then the primary and the secondary properties will be tried in turn, before returning either the unchanged input, or the default value. The property ${/} is replaced with System.getProperty("file.separator") value and the property ${:} is replaced with System.getProperty("path.separator").
To know how it is done, you can take a look at org.jboss.metadata.MetaData.java. And here is the documentation from the Javadoc:
Go through the input string and replace any occurance of ${p} with the System.getProperty(p) value. If there is no such property p defined, then the ${p} reference will remain unchanged. If the property reference is of the form ${p:v} and there is no such property p, then the default value v will be returned. If the property reference is of the form ${p1,p2} or ${p1,p2:v} then the primary and the secondary properties will be tried in turn, before returning either the unchanged input, or the default value. The property ${/} is replaced with System.getProperty("file.separator") value and the property ${:} is replaced with System.getProperty("path.separator").
2006-05-08
Implementing web service on JBoss 4.0.3
My recent project involves implementing web services on JBoss platform. The current implementation (4.0.3) is based on a modified Axis code base and does not provides a good support on top-down (starts from WSDL) development approach. I ended up have to integrate Axis 1.2 with JBoss 4.0.3. It works well so far.
At the same time, I have been looking into the next generation of JBoss WS which looks like very promising. During the course, I was also able to make some contribution to the new code base, fixing two defects (JBWS 754-755). I hope I will have more time in the future to make more contributions.
At the same time, I have been looking into the next generation of JBoss WS which looks like very promising. During the course, I was also able to make some contribution to the new code base, fixing two defects (JBWS 754-755). I hope I will have more time in the future to make more contributions.
A maven 1.x plug-in for Agitar
I have been spending some time to create a Maven 1.x plug-in for Agitar . It was finally done last week and I have posted it on Agitar's forum .
2006-04-05
Bitten by Maven
I have been struggling with my Maven script for a few hours. Finally it turned out is because of a property name I used. After I changed the name from "someA-someB" to "someA.someB", the problem is gone. Maven just does not like '-'.
2006-02-16
2 tips about JBoss
* to retrieve the server name, such as "minimal", "default", "max", in your code
* to set an unique Xid for each JBoss instance
if you are running multiple JBoss instances on the same machine, you probably want to give each instance a unique Xid base name. To do it, you need to add
the following line in the jboss-service.xml:
String serverName = System.getProperty( org.jboss.system.server.ServerConfig.SERVER_NAME); * to set an unique Xid for each JBoss instance
if you are running multiple JBoss instances on the same machine, you probably want to give each instance a unique Xid base name. To do it, you need to add
the following line in the jboss-service.xml:
<mbean code="org.jboss.tm.XidFactory" name="jboss:service=XidFactory">
<attribute name="BaseGlobalId">UniqueInstanceName</attribute>
<!--attribute name="Pad">true</attribute-->
</mbean>
2006-02-13
Upgrade to CruiseControl 2.4.0
Today I upgraded my CruiseControl to 2.4.0. The main reason is my project's SCM has been moved from Visual Source Safe to Perforce and I cannot get the CruiseControl 2.2.1 to work with Perforce. After the upgrade, everything comes back to normal.
2006-02-02
Complex test data setup in Fitnesse
I am creating functional specifications using Fitnesse for one of my systems. The system is a typical messaging system following the request/response pattern. Writing Fitnesse for this kind of system is straight forward and falls nicely into the BuildOperateCheck pattern. The only problem is that some types of requests are really really complex which could contain up to a few hundred different data fields. It is obviously not practical to setup all these fields in one table row using the ColumnFixture. I am thinking about how to deal with it.
One approach is to identify a small set of data fields that we will focus on testing on each page and create a fixture table that deals with only that small set of data. For the rest of the fields, we just assign some default values.
It is a reasonable assumption. Because on each Fitnesse page we usually test a specific requirement that most likely only involves several variables. For example, if I am designing a online book purchase system which is very complicated. But one of the requirement is to identify the tax rate. The tax rate are identified by the customer's postal code and county. Thus I only need to include "postal code" and "county" in my fixture table and I will be able to test that requirement.
In some rare cases, even that small set of data does not fit well in one table. In that situation, I managed to use multiple tables to collect the data for building a single request. It takes a little extra work but it makes the page more readable.
One approach is to identify a small set of data fields that we will focus on testing on each page and create a fixture table that deals with only that small set of data. For the rest of the fields, we just assign some default values.
It is a reasonable assumption. Because on each Fitnesse page we usually test a specific requirement that most likely only involves several variables. For example, if I am designing a online book purchase system which is very complicated. But one of the requirement is to identify the tax rate. The tax rate are identified by the customer's postal code and county. Thus I only need to include "postal code" and "county" in my fixture table and I will be able to test that requirement.
In some rare cases, even that small set of data does not fit well in one table. In that situation, I managed to use multiple tables to collect the data for building a single request. It takes a little extra work but it makes the page more readable.
Fitnesse and coding convention
I have recently started to use Fitnesse to document the requirements of two of my projects. It is a wonderful tool that not only makes writing requirement more fun, but also makes the process works. Many of us are used to hundreds of pages of requirement document that only satisfies the "process police" but does little help to developers. The requirements written in Fitnesse is live and up to date. It just works!
But there is one thing I am scratching my head now which is the coding convention used by Fitnesse. For many fixtures, such as RowFixture, the convention is to match the column name to a public member variable in the fixture class. The traditional getter and setter approach is not supported here.
Many people oppose the idea of getter and setter and consider them evil. I am ok to either approaches. But the problem is the coding convention adopted by my organization is to have each member variable prefixed by the "m" and all member variables should be accessed through getters and setters. I cannot find a way to reconcile this problem. I won't be a problem to make a special case for this, but I really hope Fitnesse can support both approaches.
But there is one thing I am scratching my head now which is the coding convention used by Fitnesse. For many fixtures, such as RowFixture, the convention is to match the column name to a public member variable in the fixture class. The traditional getter and setter approach is not supported here.
Many people oppose the idea of getter and setter and consider them evil. I am ok to either approaches. But the problem is the coding convention adopted by my organization is to have each member variable prefixed by the "m" and all member variables should be accessed through getters and setters. I cannot find a way to reconcile this problem. I won't be a problem to make a special case for this, but I really hope Fitnesse can support both approaches.
2006-01-31
Stomp
I have previous written about using web service as a mediator to let languages other than Java to communicate with JMS server. The approach is only for simple usage such as a testing tool. For more advanced usages, we can consider Stomp whcih is an open messaging protocol. There are various clients exist for Perl, Python and Ruby. On the server side, however, there is only ActiveMQ support.
2006-01-26
Make Perl speak JMS (2)
Now the WSDL is ready, I can start to implement the WS server in Java. The tool of choice is Apache Axis 1.2.1.
With the wsdl2java tool, it is straight forward to generate the codes from the WSDL file. Because we will only use the server code, so we only need to change one class HttpBindingImpl.java.
Here we just forward the request to the MessageRouter class and let it handle the details.
Axis provides several different ways to deploy the web services. The most convenient way is to use JWS file but it has certain limitations. Here I choose to use the WSDD file and embed the Axis engine in the Tomcat servlet container. As of how to integrate Axis with a servlet container, I could not find a good documentation. Eventually I figured it out and here is the code
The deployment descriptor for the servlet is:
With the wsdl2java tool, it is straight forward to generate the codes from the WSDL file. Because we will only use the server code, so we only need to change one class HttpBindingImpl.java.
private MessageRouter mRouter = new MessageRouter();
public code.simple.www.router._2005._11._7.RouteResponseType routeMessage
(code.simple.www.router._2005._11._7.RouteRequestType document)
throws java.rmi.RemoteException
{
try
{
return mRouter.routeMessage(document);
}
catch(Exception ee)
{
throw new RemoteException("Failed to route the message", ee);
}
}
Here we just forward the request to the MessageRouter class and let it handle the details.
Axis provides several different ways to deploy the web services. The most convenient way is to use JWS file but it has certain limitations. Here I choose to use the WSDD file and embed the Axis engine in the Tomcat servlet container. As of how to integrate Axis with a servlet container, I could not find a good documentation. Eventually I figured it out and here is the code
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
PrintWriter pw = null;
try
{
pw = resp.getWriter();
resp.setContentType(CONTENT_TYPE);
String reqMsg = readContent(req.getReader());
mLogger.info("Got WS request:\n" + reqMsg);
MessageContext msgContext = new MessageContext(mAxisServer);
msgContext.setRequestMessage(new Message(reqMsg));
msgContext.setTargetService("MessageRouterPort");
String respMsgStr = null;
try
{
mAxisServer.invoke(msgContext);
respMsgStr = msgContext.getResponseMessage().getSOAPPartAsString();
}
catch (AxisFault fault)
{
Message respMsg = msgContext.getResponseMessage();
if (respMsg == null)
{
respMsg = new Message(fault);
((org.apache.axis.SOAPPart)respMsg.getSOAPPart()).
getMessage().setMessageContext(msgContext);
}
respMsgStr = respMsg.getSOAPPartAsString();
}
mLogger.info("Got WS response:\n" + respMsgStr);
pw.write(respMsgStr);
}
catch (Exception me)
{
mLogger.error(me);
throw new ServletException(me);
}
finally
{
if (pw != null)
{
pw.close();
}
}
}
public void init(ServletConfig cfg) throws ServletException
{
super.init(cfg);
EngineConfigurationFactory factory =
EngineConfigurationFactoryFinder.newFactory(cfg);
EngineConfiguration config = factory.getServerEngineConfig();
mAxisServer = new AxisServer(config);
}
The deployment descriptor for the servlet is:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app >
<servlet>
<servlet-name>MessageRoutingServlet</servlet-name>
<servlet-class>code.simple.MessageRoutingServlet</servlet-class>
<init-param>
<param-name>servletId</param-name>
<param-value>defaultServlet</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>MessageRoutingServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
2006-01-18
The SimpleDateFormat class is NOT threadsafe
In researching a defect in my project, I find SimpleDateFormat class is not thread safe. The "bug" is reported back in JDK 1.2 and JavaDoc is added in JDK 1.5. I just don't see it. :(
Subscribe to:
Posts (Atom)