Tuesday, August 28, 2007

Migrate WASD 5.1 Application to RSA 7.0/WAS 6.1

Get the application source from Harvest repository. Disconnect Harvest connection.

Create a new web project and ear project in RSA on a new folder. Import source code from the old folder. Compile passed.

Deploy to the embedded WAS 6.1. Run.

Find the tld path problem. Old web.xml sets tlds under WEB_INF/, now application looks tlds under WEB_INF/tlds. Edit web.xml and fix it. WAS 6.1 automatically republishes the app and restart the app.

Get this exception.
[8/28/07 10:49:14:485 EDT] 00000036 WebApp E Exception caught while initializing context
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator' defined in ServletContext resource [/WEB-INF/declarativeServices.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.FatalBeanException: Could not instantiate class [org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator]; constructor threw exception; nested exception is java.lang.NoSuchMethodError: org/objectweb/asm/ClassVisitor.visit(IILjava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)V
org.springframework.beans.FatalBeanException: Could not instantiate class [org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator]; constructor threw exception; nested exception is java.lang.NoSuchMethodError: org/objectweb/asm/ClassVisitor.visit(IILjava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)V
java.lang.NoSuchMethodError: org/objectweb/asm/ClassVisitor.visit(IILjava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)V
Search Google. Find talks on incompatibility of asm, cglib, spring and hibernate. We are using
  • spring-1.2.6
  • hibernate-3.1.2
  • asm-1.5.3
  • cglib-2.1_3
Try to obtain the ear file from production system and deploy to WAS 6.1.

Encounter the same exception.

Several combinations tried. Finally this one worked.

Download spring-framework-1.2.9-with-dependencies.zip and extract the cglib-nodep-2.1_3.jar and replace the original cglib-2.1_3.jar. Redeploy the application in workspace to WAS 6.1 and restart server.

It is possibly both spring framework and hibernate depend on cglib, and further on asm, but they require different asm. cglib-nodep actually packages a revised asm, spring will have no need of a separate asm and let hiberate uses the asm exclusively. Hibernate may actually not need any cglib, but no time for this research yet.

Saturday, August 18, 2007

终于能在Red Hat中键入中文

关键是需要将默认的语言设置成简体中文,然后用Ctrl+Space在中英文之间切换。

默认的输入法是二笔,我不会,改成了智能拼音就好了。和用惯了的全拼有些区别,用用也就习惯了。

简体中文中好多系统菜单翻译得莫名其妙,试了试,不知道怎么切回英文。

Thursday, August 09, 2007

Compare Fuse Message Broker 4.1 to Apache Active MQ 4.1.1

  1. conf\activemq.xml: Fuse has one more block of comments.
  2. installsession_log.xml: only Fuse has.
  3. docs: Fuse has welcome.htm and more images.
  4. etc: only Fuse has etc folder, including license_agreement.txt and notices.txt. Apache puts these two files at the root directory.
  5. example is not compared.
  6. lib: Most differences are on the release number. Fuse is 4.1.2.4, Apache is 4.1.1. One noticable difference is Fuse has xbean-spring-fuse-2.7.0.0.jar, but Apache has xbean-spring-2.8.jar.

Monday, August 06, 2007

Unit Test - Piece of Logic Covered or Not?

Emma coverage report will show uncovered pieces of logic red. For example,
if (validField(fk.getName(), valueFK)) {
criteria.add(buildRestriction(propertyTypes[i], value, relationName));
criteriaCount.add(buildRestriction(propertyTypes[i], value, relationName));
}
In the unit test, you will need to make the validField returns true. And then the report will show them covered and mark them green.

JMS Implementation with RSA 7.0 and WAS 6.1

Environment:
IBM Rational Software Architect 7.0 with embedded WebSphere Application Server 6.1.

Purpose:
  • Create a JMS client application to send a simple message to a queue defined by WAS 6.1 default messaging provider.
  • Create a MDB to consume the message received by the queue.
Development:
  1. Open RSA, use the New wizard to create an Enterprise Application Project under J2EE group, if you cannot see this selection, check if you are using the J2EE perspective. I called the project minzy.
  2. Click "Show Runtimes" to make sure the v6.1 is selected.
  3. Click "New Modules" to create default modules, check off Web module and Connector module, which we don't need, and change the name of the EJB module to minzyEnt. It's only my preference, you can call it any name.
  4. Rename source folders to "src" in both minzyClient and minzyEnt.
  5. In minzyClient, create a package "tliu.minzy.client" and create a class "MessProducer" with main method.
  6. Delete default package.
  7. Edit MANIFEST.MF under META-INF and change Main-Class to tliu.minzy.client.MessProducer.
  8. From menu Project, select clean and select minzyClient, minzyEnt and minzy, error in minzy and minzyClient will be gone.
  9. In minzyEnt, create package tliu.minzy.ent, use New wizard to create a Enterprise Bean.
  10. Check "Message-driven bean", give name MessConsumer, select package tliu.minzy.ent and check on "Generate an annotated bean class".
  11. Make sure JMS type is javax.jms.MessageListener.
  12. Check off "Add bean to Class Diagram", diagrams are out of the scope.
  13. Now you see all error gone, we are ready to put real codes in.
Code in MessProducer:
    public static void main(String[] args) throws Exception {
InitialContext initCtx = new InitialContext();
javax.jms.ConnectionFactory qcf = (javax.jms.ConnectionFactory) initCtx.lookup("jms/minzyConnectionFactory");
Destination q = (Destination) initCtx.lookup("jms/minzyQueue");
Connection connection = qcf.createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer queueSender = session.createProducer(q);
TextMessage outMessage = session.createTextMessage();
outMessage.setText("Hello, minzy.");
outMessage.setJMSType("minzy");
outMessage.setJMSDestination(q);
queueSender.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
queueSender.send(outMessage);
connection.close();
System.out.println("Minzy mess produced.");
}
Code in MessConsumerBean:
    public void onMessage(javax.jms.Message mess) {
TextMessage text = (TextMessage) mess;
try {
System.out.println("Message Received: " + text.getText());
} catch (JMSException e) {
System.out.println("Oops, exception.");
}
}
Packaging:
Export minzyClient to C:\development\applications\minzyClient.ear.
Export minzyEnt to C:\development\applications\minzyEnt.ear.

Deployment:
  1. In Servers view in RSA, select WebSphere Application Server v6.1 and start the server.
  2. After started, right click the server and select "Run administrative console".
  3. Navigate Service integration > Buses > New and create a bus "minzyBus".
  4. Navigate minzyBus > Bus members > Add and add server "cledt-123691Node02:server1".
  5. Open a command window, and change directory to "C:\Program Files\IBM\SDP70\runtimes\base_v61\bin", run "setupCmdLine.bat".
  6. Run "wsadmin -f installSdoRepository.jacl -createDb cledt-123691Node02 server1".
  7. Verify SDO Repository successfully started under Enterprise Applications. Note, install once per server.
  8. Run "wsadmin -f ../util/sibwsInstall.jacl INSTALL_RA -installRoot "C:/Program Files/IBM/SDP70/runtimes/base_v61" -nodeName cledt-123691Node02". Note, install once per node.
  9. Run "wsadmin -f ../util/sibwsInstall.jacl INSTALL -installRoot "C:/Program Files/IBM/SDP70/runtimes/base_v61" -serverName server1 -nodeName cledt-123691Node02".
  10. Run "wsadmin -f ../util/sibwsInstall.jacl INSTALL_HTTP -installRoot "C:/Program Files/IBM/SDP70/runtimes/base_v61" -serverName server1 -nodeName cledt-123691Node02".
  11. In the admin console, navigate to Servers > Application Servers > server1 > Endpoint Listeners and select New. Specify SOAPHTTPChannel1 as name, http://cledt-123691.agna.amgreetings.com:9081/SOAPHTTPChannel1 as URL root, http://cledt-123691.agna.amgreetings.com:9081/sibws as WSDL root.
  12. Select the "Connection Properties" of SOAPHTTPChannel1, client New and select minzyBus.
  13. Go to minzyBus > Destinations, there should be a new destination called cledt-123691Node02.server1.SOAPHTTPChannel1Reply.
  14. Navigate minzyBus > Destinations > New and create a Queue type destination "minzyDestination".
  15. Navigate Resources > JMS Providers > Default messaging. Select Node as the scope.
  16. Select Connection factories and click New. Enter minzyConnectionFactory as name, jms/minzyConnectionFactory as JNDI name, select minzyBus, enter localhost:7277 in the "Provider endpoints" box, leave other default and click OK.
  17. Go back to Default messaging provider and select Queues. Click New.
  18. Enter minzyQueue as name, jms/minzyQueue as JNDI name, select minzyBus and minzyDestination. Click OK.
  19. Go back to Default messaging provider and select Activation specifications. Click New.
  20. Enter minzyActivation as name, eis/minzyActivation as JNDI name, jms/minzyQueue as Destination JNDI name and select minzyBus. Click OK and save all your changes.
  21. Install minzyEnt.ear in admin console. Make sure Deploy enterprise beans are checked. Enter eis/minzyActivation as Activation Specification Target and jms/minzyQueue as Destination.
  22. Restart server.
Run:

In a command line window, change directory to C:\Program Files\IBM\SDP70\runtimes\base_v61\bin. Run,

setupCmdLine.bat
launchClient \development\applications\minzyClient.ear -CCBootstrapPort=2810

In the command line window, you shall see,
WSCL0014I: Invoking the Application Client class tliu.minzy.client.MessProducer
Minzy mess produced.

In the server console, you shall see,
[8/6/07 13:33:32:455 EDT] 0000002f SystemOut O Message Received: Hello, minzy.

The End.

Thursday, August 02, 2007

WAS 6.1 - JMS Default Provider Administrative Aspect

In WAS 6.1, there is a default messaging JMS provider. It comes with WAS 6.1.

To list messages in a queue, go through this path,

Service integration > Buses > [TheBus] > Messaging engines > [cledt-123691Node01.server1-TheBus] > Queue points > [MyQueueDestination@cledt-123691Node01.server1-TheBus] > Runtime

you see the "Current message depth".

Select "Messages", you see messages and their position, identifier, state and transaction id. You can select any of them and click "Delete" or just click "Delete all" to delete them from the queue.

The message's identifier is actually a link. Click it to get the detail of the message. It shows
identifier, state, transaction id, message type, approximate length, time stamp, message wait time, current messaging engine arrival time, redelivered count, security user id, producer type, message id, correlation id, user id, format, JMS delivery mode, JMS expiration, JMS destination, JMS reply to destination, JMS redelivered, JMS type, JMSX delivery count, JMSX application id, discriminator, priority, reliability, time to live, reply discriminator, reply priority, reply reliability, reply time to live and system message id. All attributes are read only.

Click "Message body", you will get "Approximate total message size" in bytes, message body. The message body is also read only.

You can define Performance Monitoring Infrastructure(PMI) to collect JMS runtime statistics. You will need a PMI client to view these statistics. So far, Tivoli Performance Viewer(TPV) is the only known PMI client to us. TPV has not been tested so far. According to IBM, TPV comes with WAS 6.1 and is free.