IBM WebSphere Developer Technical Journal

IBM WebSphere Developer Technical Journal February 2005 -- Issue 8.1 This month's articles: Developing a standalone Java application for WebSphere MQ System management for WebSphere Application Server V6 -- Part 2: Incremental cell upgrade Building an Enterprise Service Bus with WebSphere Application Server V6 -- Part 2: Business requirements and the bus Using the Java Secure Socket Extension in WebSphere Application Server -- What is the JSSE all about? Accelerated JSF development for XML-based SOA using Rational Application Developer and WebSphere Application Server -- Part 3: Manipulating SDO instances This month's features: from Roland Barcia: Examining the EJB 3.0 Simplified API specification The EJB Advocate: Making entity EJB components perform From the Editor This issue of the IBM® WebSphere® Developer Technical Journal focuses on IBM WebSphere Application Server, continuing several series of articles on important new product features: Our system administration series highlights the incremental cell upgrade process in WebSphere Application Server V6. Our Enterprise Service Bus series describes a business case for building an ESB. Our series on JSF development for SOA offers tips for manipulating the functionality of SDO instances. Also, learn how to build a J2SE messaging application -- without an application server, and how to use the IBM Java™ Secure Socket Extension in a WebSphere Application Server environment. Roland Barcia also returns to offer on a segment of the upcoming EJB™ 3.0 specification. Plus, The EJB Advocate is back, this time helping a customer who is disillusioned over entity EJB performance. Check out these articles and more below... Developing a standalone Java application for WebSphere MQ J2EE™ applications that use Java Messaging Service (JMS) messaging are common, and there is plenty of documentation on how to make them work well. What is less well-documented is how to create a Java 2 Standard Edition (J2SE) application -- one without the benefits of an application server -- that uses a JMS messaging provider. Such a standalone application is possible, and in this article, Bobby Woolf shows how to make it work with WebSphere MQ as a JMS and JNDI client, still taking advantage of JMS asynchronous messaging, without having to be deployed in a J2EE application server. System management for WebSphere Application Server V6 -- Part 2: Incremental cell upgrade Continuing this popular series on the system management functionality enhancements in WebSphere Application Server V6, Michael Cheng launches the first of the feature-specific articles outlined in the Part 1 overview. Here, we learn about the incremental cell upgrade process, how it works, what it all means to system administrators, and why the ability to upgrade a cell one node at a time is a significant improvement over prior methods of updating cells to a newer version of WebSphere Application Server. Future articles in this series will each focus on a specific feature, so stay tuned. file:///C|/developerworks/pdf_0502/index.html (1 of 2) [2/23/2005 6:49:44 PM] IBM WebSphere Developer Technical Journal Building an Enterprise Service Bus with WebSphere Application Server V6 -- Part 2: Business requirements and the bus Last month, in Part 1 of this series, Rachel Reinitz and Andre Tost introduced us to the core concepts and features of WebSphere V6 Messaging Resources, the new messaging engine in WebSphere Application Server V6 that can be used to build an Enterprise Service Bus (ESB). This month, they describe a business case for building an ESB, and show how to set up a bus instance for use with Web services. Part 2 puts the architecture is a business context and sets the stage for the ESB development, still to come. Using the Java Secure Socket Extension in WebSphere Application Server: What is the JSSE all about? WebSphere Application Server fully supports Java Secure Socket Extension (JSSE), both as a Service Provider Interface to the framework, and as a set of user APIs. As such, JSSE is readily available for applications that need to establish SSL/TLS connections within the WebSphere Application Server environment. In this article, Messaoud Benantar and Keys Botzum examine ways for developers to use JSSE -- with a particular emphasis on JSSE configuration, aspects of keystore and truststore, and how to maintain application portability. Accelerated JSF development for XML-based SOA using Rational Application Developer and WebSphere Application Server -- Part 3: Manipulating SDO instances This article series, which presents an accelerated JavaServer™ Faces development solution for an XML-based SOA application, continues with a look at common techniques for manipulating the functionality of SDO instances. In Part 3, Narinder Makin builds upon the SDOs developed in Part 1 and extended in Part 2 with tips for XML SDO usage in IBM Rational® Application Developer, and for using aggregate methods, the SDO generator, and more. Extensive code samples and download files are provided. file:///C|/developerworks/pdf_0502/index.html (2 of 2) [2/23/2005 6:49:44 PM] IBM WebSphere Developer Technical Journal: Developing a standalone Java application for WebSphere MQ IBM WebSphere Developer Technical Journal: Developing a standalone Java application for WebSphere MQ Level: Introductory Bobby Woolf WebSphere J2EE Consultant, IBM Software Services for WebSphere 23 Feb 2005 Contents: Introduction Why a standalone application? Developing point-to-point This article shows how to develop a J2SE Java™ application that sends and receives Developing messages using IBM® WebSphere® MQ. The application uses the standard JMS publish/subscribe and JNDI APIs from J2EE™, but does not require being deployed in a J2EE Conclusion application server. Resources Introduction Download J2EE applications that use Java Messaging Service (JMS) messaging are common, and About the author there's plenty of documentation on how to make them work well. What is less welldocumented is how to make a Java 2 Standard Edition (J2SE) application -- one without the Rate this article benefits of an application server -- using a JMS messaging provider. This article shows Related content: how to make a standalone Java application work with WebSphere MQ as a JMS and JNDI client. Such an application can still take advantage of JMS asynchronous messaging IBM WebSphere Developer without having to be deployed in a J2EE application server, such as IBM WebSphere Technical Journal Application Server. Why a standalone application? The first question one might ask is: Why configure a standalone application to use asynchronous messaging? J2SE is designed for developing simple applications that usually run in a single Java virtual machine (JVM) on one computer. The applications that generally use messaging are developed on the Java 2 Enterprise Edition (J2EE) platform, which provides a variety of services for enterprise applications, including messaging. Messaging is provided by JMS, which includes a standard API for accessing messaging systems. JMS applications also use the Java Naming and Directory Interface (JNDI) API to access the messaging system's managed resources, namely connection factories and destinations. Even an application designed to run for a single user on the desktop may need to integrate with other applications and services. Such an application can benefit from using asynchronous messaging to do so, and, as a Java application, should use the JMS API (with JNDI) to perform messaging. Standalone JMS You may already have an application written that uses JMS and JNDI. This article includes a download file containing a simple example of JMS clients which run via main() methods. While this is hardly a useful application, it is adequate to demonstrate messaging. We will walk through how we modified the sample application to work with WebSphere MQ; you would make similar changes to your application. The sample application works much like a J2EE program in that it uses JNDI to access managed resources (connection factories and destinations) from the JMS provider, and uses JMS to send and receive messages. (The application does not use message-driven beans because those are a type of Enterprise JavaBean™, and would require this application to be a J2EE application.) file:///C|/developerworks/pdf_0502/0502_woolf/0502_woolf.html (1 of 10) [2/23/2005 6:49:52 PM] IBM WebSphere Developer Technical Journal: Developing a standalone Java application for WebSphere MQ The configuration shown in this article makes the following assumptions: q q q You are using WebSphere MQ V5.3 for Microsoft® Windows®. Versions for other platforms should work as well but have not been tested. WebSphere MQ is installed on your local machine (which is referred to in the URLs as localhost). Your WebSphere MQ installation has a queue manager named QMGR whose TCP listener is running on port 1414. If your WebSphere MQ installation is different, you will need to modify these instructions and samples accordingly. Developing point-to-point First we will look at how to set up point-to-point messaging using queues. Configuring the application and the messaging system requires the following steps: 1. 2. 3. 4. 5. 6. Obtain and install support pacs for WebSphere MQ. Modify your application's JNDI code to use the support pacs. Modify the administration tool to use the support pacs. Configure WebSphere MQ with the necessary JMS resources. Create or modify an application execution script that uses the support pacs. Run the application. The code modifications necessary are minimal, and in fact can be limited to modifying a jndi.properties file if your code uses one. The main change related to your code is to modify the script for running the code so that it has the necessary Java application resource (JAR) files on its classpath. 1. Obtain and install support pacs for WebSphere MQ This example uses WebSphere MQ Version 5.3. Out of the box, this version does not provide everything you need to support a JMS program. It includes an implementation of the JMS interface, but not the JNDI interface. To add support for JNDI to WebSphere MQ, you need to install support pac ME01 (WebSphere MQ Initial Context), which in turn requires support pac MS0B (MQSeries Java classes for PCF). (See Resources.) To install these support pacs, simply unzip them. Each contains a JAR file you'll need later. (The sample scripts assume you add the JAR files to the WebSphere MQ Java\lib directory.) Other than making sure you have the JAR files available and reading the accompanying documentation, there's no further installation to perform. 2. Modify your application's JNDI code to use the support pacs In a J2EE application, using JNDI is pretty easy. You simply create an InitialContext (with no parameters) and start using it. This is because the J2EE container manages the JNDI contexts, including the one for the component (Web application or EJB class) that contains your code. For a J2SE (standalone) application, there is no J2EE container managing the JNDI contexts, just a simpler J2SE container (basically a plain JVM). The component model is much simpler -- no Web applications, no EJBs -- so all code has the same JNDI context. Therefore, establishing an initial JNDI context requires more work in J2SE. In J2EE, you can usually simply say: Context context = new InitialContext(); file:///C|/developerworks/pdf_0502/0502_woolf/0502_woolf.html (2 of 10) [2/23/2005 6:49:52 PM] IBM WebSphere Developer Technical Journal: Developing a standalone Java application for WebSphere MQ with no parameters and get the JNDI context you need. In J2SE, creating the initial context is a little more difficult. You need to use a different constructor, InitialContext(Hashtable), like this: Properties env = new Properties(); // fill in the context properties Context context = new InitialContext(env); The context properties tell JNDI what context you want so that it can create the right one for you. In this case, we want one for accessing WebSphere MQ, namely the instance we have installed. To do so, we use code like this: Properties env = new Properties(); env.put( Context.INITIAL_CONTEXT_FACTORY, "com.ibm.mq.jms.context.WebSphere.MQInitialContextFactory"); env.put(Context.PROVIDER_URL, "localhost:1414/SYSTEM.DEF.SVRCONN"); Context context = new InitialContext(env); This code sets a pair of context properties: q q INITIAL_CONTEXT_FACTORY The name of the class JNDI we will use to create the InitialContext. Because we want to access WebSphere MQ through JNDI, the initial context factory we use is a WebSphere MQ class. (This class is provided by the ME01 support pac described above.) PROVIDER_URL Specifies how to find our running WebSphere MQ installation. Much like the URL for an HTML file or a JDBC data source, the information in this URL tells JNDI how to find and access WebSphere MQ using the implementation provided by the support pac. Your PROVIDER_URL may need to differ from the value shown here. If your WebSphere MQ install is on a different computer from the one you will run your client application on, you need to change localhost to the hostname or IP address of the WebSphere MQ machine. Likewise, port 1414 is the default listener port number for the first queue manager in WebSphere MQ. If your install's port number is different, or you want to use a different queue manager, you need to specify its port. And that's it. That's all the code you need to change, the code for instantiating an initial JNDI context. From there, your code works the same. It uses JNDI to access the JMS connection factory and JMS queue, and uses them to send and receive messages. You can even store these JNDI context properties in a properties file (the standard name is jndi.properties) and then modify them without having to change (and recompile and re-JAR) any code at all. 3. Modify the administration tool to use the support pacs The JMS administration tool for WebSphere MQ is called JMSAdmin.bat, located in the Java\bin directory of file:///C|/developerworks/pdf_0502/0502_woolf/0502_woolf.html (3 of 10) [2/23/2005 6:49:52 PM] IBM WebSphere Developer Technical Journal: Developing a standalone Java application for WebSphere MQ the MQ install directory. It needs to be modified to use the MS0B and ME01 support pacs. Modify the script's classpath to add the support pacs' com.ibm.mq.pcf.jar and mqcontext.jar JAR files, something like this (if the JAR files were in the bin directory, which isn't really a good place): set CLASSPATH=%CLASSPATH%;mqcontext.jar;com.ibm.mq.pcf.jar The script will use the new classpath when it runs the administration class, com.ibm.mq.jms.admin.JMSAdmin. The JMS administration tool's configuration file, JMSAdmin.config, also needs to be modified. Add lines to the file (and comment out any corresponding lines) to make the following settings: INITIAL_CONTEXT_FACTORY=com.ibm.mq.jms.context.WebSphere.MQInitialContextFactory PROVIDER_URL=localhost:1414/SYSTEM.DEF.SVRCONN Again, the URL for your installation may be different. In any case, these values are the same as what you used in your application's JNDI code. (JMSAdmin is just another WebSphere MQ client, just like your application.) 4. Configure WebSphere MQ with the necessary JMS resources The JMS administration tool runs interactively, but it is easier to have it process a script that can be edited and run repeatedly. The script's filename can be anything; by convention, the extension is .scp. In this example, the filename is sampleconfig.scp. The two lines of interest right now are these: def qcf(SampleQCF) qmgr(QMGR) tran(client) chan(SYSTEM.DEF.SVRCONN) + host(localhost) port(1414) def q(SampleQueue) qmgr(QMGR) qu(SAMPLE.QUEUE) These two lines create a javax.jms.QueueConnectionFactory with the JNDI name SampleQCF and a javax.jms.Queue named SampleQueue. This script assumes the queue manager is named QMGR; modify the script if your queue manager is named differently. Like the PROVIDER_URL value used earlier, if your install is running on a different machine or your queue manager is running on a different port, you will need to modify these settings in your script. Once the script is ready, you run it from a command line like this: C:\WebSphere MQ\Java\bin> JMSAdmin -v < sampleconfig.scp In the WebSphere MQ Explorer, you should now see a queue named SampleQueue in the Console Root\WebSphere MQ\Queue Managers\QMGR\Queues folder. file:///C|/developerworks/pdf_0502/0502_woolf/0502_woolf.html (4 of 10) [2/23/2005 6:49:52 PM] IBM WebSphere Developer Technical Journal: Developing a standalone Java application for WebSphere MQ 5. Create or modify an application execution script that uses the support pacs The sample scripts for running the JMS clients require these items in the classpath: q q q q q q JMS API: %MQ_JAVA_INSTALL_PATH%/lib/jms.jar J2EE Connector API: %MQ_JAVA_INSTALL_PATH%/lib/connector.jar WebSphere MQ client: %MQ_JAVA_INSTALL_PATH%/lib/com.ibm.mq.jar WebSphere MQ JMS implementation: %MQ_JAVA_INSTALL_PATH%/lib/com.ibm.mqjms.jar MS0B support pac JAR file: com.ibm.mq.pcf.jar ME01 support pac JAR file: mqcontext.jar As explained earlier, the application's JNDI code must set the INITIAL_CONTEXT_FACTORY and PROVIDER_URL values. If those settings are being read from a jndi.properties file, it will need to be in the application's classpath as well. 6. Run the application Now we're ready to test the application. Open two command windows, one for the sender and one for the receiver. Go to the directory with the sample code, and run the sender and receiver. Then type in a message like, this is a test. You should see this in the sender window: C:\standalonewmq> StandaloneSender java -cp "standalonewmq.jar;. . ." com.ibm.examples.StandaloneSender Sender started. Enter a message: this is a test Sent message with ID Enter a message: Sender stopped. C:\standalonewmq> And this is what you should see in the receiver window: C:\standalonewmq> StandaloneReceiver java -cp " standalonewmq.jar;. . ." com.ibm.examples.StandaloneReceiver Receiver started. Received message with ID Receiver stopped. C:\standalonewmq> The result shows that a message containing this is a test with an ID ending in 20005001 was sent and received. file:///C|/developerworks/pdf_0502/0502_woolf/0502_woolf.html (5 of 10) [2/23/2005 6:49:52 PM] IBM WebSphere Developer Technical Journal: Developing a standalone Java application for WebSphere MQ The example works. Developing publish/subscribe The sample application also includes a publisher and subscriber for a topic. This publish/subscribe example assumes you have already done the setup for point-to-point messaging. The following additional steps are required: 1. 2. 3. 4. 5. Obtain and install the publish/subscribe support pac for WebSphere MQ. Configure WebSphere MQ for publish/subscribe and start the broker. Configure WebSphere MQ with the necessary JMS resources. Create or modify an application execution script. Run the application. We already performed the other steps when we setup WebSphere MQ for the point-to-point part of the example. 1. Obtain and install the publish/subscribe support pac for WebSphere MQ WebSphere MQ V5.3 does not include support for publish/subscribe. For that, you need to add support pac MA0C (WebSphere MQ (MQSeries) - Publish/Subscribe). The latest fix packs for WebSphere MQ V5.3 (such as Fix Pack 8, CSD08) include MA0C, so if you already have a recent fix pack installed, you can skip installing MA0C. If you're not sure whether or not you have the support pac installed, go ahead and try to install it. If it is already installed, the installer will simply tell you so and then automatically exit. To install the support pac, download it (see Resources), run it, and follow the instructions in the wizard. 2. Configure WebSphere MQ for publish/subscribe and start the broker Once you have the publish/subscribe support pac installed, you need to configure and start it. At this point, if you were to try running the publisher or subscriber (go ahead and try, if you like), you would get this error: Supporting publish/subscribe Other IBM products, including WebSphere Business Integration Event Broker and WebSphere Business Integration Message Broker, support publish/subscribe implemented not only with WebSphere MQ, but also with other implementations, such as IP multicast. Those products are beyond the scope of this article. javax.jms.JMSException: MQJMS5087: Unexpected error 2085 accessing internal queue SYSTEM.JMS.REPORT.QUEUE This error indicates that the internal queues WebSphere MQ requires to support JMS publish/subscribe have not been created. To create these queues, run the program runmqsc in the WebSphere MQ bin directory (not the Java\bin directory) with the configuration file MQJMS_PSQ.mqsc on the appropriate queue manager (again, assuming your queue manager is named QMGR). When you run the command, you should see output like this: file:///C|/developerworks/pdf_0502/0502_woolf/0502_woolf.html (6 of 10) [2/23/2005 6:49:52 PM] IBM WebSphere Developer Technical Journal: Developing a standalone Java application for WebSphere MQ C:\WebSphere MQ\bin> runmqsc QMGR < MQJMS_PSQ.mqsc . . . 8 MQSC commands read. No commands have a syntax error. All valid MQSC commands were processed. Make sure the queue manager's publish/subscribe broker is running. To check, run the dspmqbrk command. It's probably not running, so the output looks like this: C:\WebSphere MQ\bin> dspmqbrk -m QMGR MQSeries Publish/Subscribe broker for queue manager QMGR not active To start it, run the command strmqbrk: C:\WebSphere MQ\bin> strmqbrk -m QMGR MQSeries Publish/Subscribe broker started for queue manager QMGR. If you run dspmqbrk again, this time it should say that the broker is running. (You can stop it later by running endmqbrk -m QMGR.) 3. Configure WebSphere MQ with the necessary JMS resources We now need to configure WebSphere MQ with a topic connection factory and a topic. If you already ran the sampleconfig.scp earlier: C:\WebSphere MQ\Java\bin> JMSAdmin -v < sampleconfig.scp then you have already created these resources and don't need to run it again. But let's take a look at what this part of the script is doing. The two relevant lines from the configuration script are these (again, assuming your queue manager is named QMGR): def tcf(SampleTCF) qmgr(QMGR) def t(SampleTopic) topic(sampletopic) The first line creates a javax.jms.TopicConnectionFactory registered in JNDI under the name SampleTCF. The second line creates a javax.jms.Topic named SampleTopic. 4. Create or modify an application execution script file:///C|/developerworks/pdf_0502/0502_woolf/0502_woolf.html (7 of 10) [2/23/2005 6:49:52 PM] IBM WebSphere Developer Technical Journal: Developing a standalone Java application for WebSphere MQ The sample scripts for running the JMS clients must have the classpath items listed for point-to-point. In addition, the publish/subscribe support uses XA (that is, distributed transactions), so the scripts also need this item in the classpath: q the JTA API: %MQ_JAVA_INSTALL_PATH%/lib/jta.jar 5. Run the application We are now ready to test publishing. Open three command windows, one for the publisher and two for two subscribers. Go to the directory with the sample code, and run the publisher and subscribers. Then type in a message, like broadcast this and you should see this in the publisher window: C:\standalonewmq> StandalonePublisher java -cp "standalonewmq.jar;. . ." com.ibm.examples.StandalonePublisher Publisher started. Enter a message: broadcast this Published message with ID Enter a message: Publisher stopped. C:\standalonewmq> You should see this in one subscriber window: C:\standalonewmq> StandaloneSubscriber java -cp "standalonewmq.jar;. . ." com.ibm.examples.StandaloneSubscriber Subscriber started. Received message with ID Subscriber stopped. C:\standalonewmq> And this in the other subscriber window: C:\standalonewmq> StandaloneSubscriber java -cp "standalonewmq.jar;. . ." com.ibm.examples.StandaloneSubscriber Subscriber started. Received message with ID Subscriber stopped. C:\standalonewmq> The single published message was sent to both subscribers. Each subscriber's message has a different ID because each subscriber gets its own copy of the message. file:///C|/developerworks/pdf_0502/0502_woolf/0502_woolf.html (8 of 10) [2/23/2005 6:49:52 PM] IBM WebSphere Developer Technical Journal: Developing a standalone Java application for WebSphere MQ Conclusion In this article, we've seen how a J2SE application can use WebSphere MQ using JMS and JNDI, without needing to be deployed in a J2EE container (such as WebSphere Application Server). We have seen: q q q q q How to get the proper JNDI initial context. How to set the classpath appropriately using the JAR files included with WebSphere MQ. What support pacs you need and how to use them. How to configure WebSphere MQ. How to administer WebSphere MQ resources so that they can be accessed as JMS resources using JNDI. You are now prepared to convert your existing applications and develop new ones. Resources IBM products q WebSphere MQ Trial version of WebSphere MQ 5.3 WebSphere Business Integration - Event Broker (WBI-EB) WebSphere Business Integration - Message Broker (WBI-MB) q q q IBM support q The IBM WebSphere MQ support site The IBM support site for all products Support pac MS0B - MQSeries Java classes for PCF Support pac ME01 - WebSphere MQ - Initial Context Factory Support pac MA0C - WebSphere MQ (MQSeries) - Publish/Subscribe q q q q Java specifications q Java Technology - Java 2 Platform, Standard Edition (J2SE) Core Java - Java Naming and Directory Interface (JNDI) Java Technology - Java 2 Platform, Enterprise Edition (J2EE) J2EE - Java Message Service (JMS) J2EE - Enterprise JavaBeans Technology (EJB) q q q q Other resources file:///C|/developerworks/pdf_0502/0502_woolf/0502_woolf.html (9 of 10) [2/23/2005 6:49:52 PM] IBM WebSphere Developer Technical Journal: Developing a standalone Java application for WebSphere MQ q WebSphere MQ Using Java (IBM Publication SC34-6066-02; January 2004) MQSeries Publish/Subscribe Applications (IBM RedBook SG24-6282-00; September 2001) Introducing the Java Message Service Writing Java Message Service programs using WebSphere MQ and WebSphere Studio Application Developer, Part 1 Writing Java Message Service programs using WebSphere MQ and WebSphere Studio Application Developer, Part 2 Creating and Testing a Message-Driven Bean using WebSphere Studio Application Developer Develop an Asynchronous Logging Framework using log4j with JMS and WebSphere MQ JMS Topologies and Configurations with WebSphere Application Server and WebSphere Studio Version 5 JMS Applications with WebSphere Studio V5 -- Part 1: Developing a JMS Point-to-Point Application JMS Applications with WebSphere Studio V5 -- Part 2: Developing a JMS Publish-Subscribe Application JMS Applications with WebSphere Studio V5 -- Part 3: Developing a Publish-Subscribe Message-Driven Bean Writing a standalone JMS application with WebSphere Studio V5.1 Developing and Testing Message-driven Bean Applications with the MQ Simulator for Java Developers in WebSphere Studio V5.0 How WebSphere Application Server handles poison messages q q q q q q q q q q q q q Download Name Size Download method StandaloneWMQCode.zip 16 KB FTP | HTTP Information about download methods About the author Bobby Woolf is a WebSphere J2EE Consultant for IBM Software Services for WebSphere (ISSW). Bobby assists clients in developing applications for WebSphere Application Server using WebSphere Studio Application Developer. He is a coauthor of Enterprise Integration Patterns and The Design Patterns Smalltalk Companion. He also has a blog on the IBM developerWorks Web site called J2EE in Practice. Bobby is a frequent conference speaker. file:///C|/developerworks/pdf_0502/0502_woolf/0502_woolf.html (10 of 10) [2/23/2005 6:49:52 PM] IBM WebSphere Developer Technical Journal: System management for WebSphere Application Server V6 -- Part 2 IBM WebSphere Developer Technical Journal: System management for WebSphere Application Server V6 -- Part 2 Incremental cell upgrade Level: Intermediate Michael Cheng (mcheng@us.ibm.com) Senior Software Engineer, IBM Software Development Lab 23 Feb 2005 This is the second in a series of articles covering the significant system management functionality enhancements in IBM® WebSphere® Application Server V6. Part 2 covers the incremental upgrade of cells from WebSphere Application Server V5 to V6. Introduction IBM WebSphere Application Server V6 contains many significant enhancements in system management functionality over the previous release, Version 5. This article series explores the evolution of the product in this area, with each article focusing on the details related to a specific feature. The articles is this series include: q q Contents: Introduction What is incremental cell upgrade? Upgrading a cell Configuration files JMX interoperability Adapt-A-View administration Runtime interoperation Using resources Working with applications Capacity planning: Working with nodes, servers and clusters Scripting compatibility Conclusion Resources About the author Rate this article Related content: IBM WebSphere Developer Technical Journal Part 1: Overview of system management enhancements Part 1: Overview of system management features Part 2: Incremental cell upgrade with additional installments on the way. What is incremental cell upgrade? Until Version 5.1 of IBM WebSphere Application Server (hereafter referred to as Application Server), upgrading a cell from a previous release to a newer release of Application Server was a time consuming process that could be disruptive to the existing environment. It was possible, for example, for the entire cell to be shut down during the upgrade. Alternatively, if an online upgrade was required, a parallel cell with the new release of Application Server would be created to mirror the existing cell, then the old cell would be taken offline after the new cell was functional. With WebSphere Application Server V5.1, the deployment manager became able to manage both file:///C|/developerworks/pdf_0502/0502_cheng/0502_cheng.html (1 of 12) [2/23/2005 6:49:58 PM] IBM WebSphere Developer Technical Journal: System management for WebSphere Application Server V6 -- Part 2 V5.0.x and V5.1 nodes, which enables the cell to be upgraded to a new release one node at a time -with minimal impact to the applications that are running within the cell. Such inconveniences associated with upgrading old releases of Application Server to the newer release had been eliminated. In Version 6.0, many additional enhancements have been introduced. Some of these enhancements, such as the adoption of JMX 1.2, or the introduction of a new messaging implementation, might have made V5 incompatible with V6, if not for measures taken specifically to ensure compatibility. Additional functions in V6, such as displaying the versions of nodes or servers from the console, adapting the console to present only information valid for a particular version node or server, and enhanced validation when modifying the configuration on different version servers or nodes through scripting or JMX APIs, further expand the administrative features that were previously available. The emphasis in V6 is to facilitate the upgrade of the entire cell in a timely fashion by giving the administrator the ability to perform rolling upgrades of individual nodes. It is still possible for an administrator to choose to not upgrade some nodes, but there are restrictions in V6, documented later in this article, with respect to what can be achieved when running such a mixed release environment for extended periods of time. Administrators are encouraged to assess their intended usage of this type of environment in the context of these restrictions. (It is anticipated that many of these restrictions will be lifted in future versions or maintenance releases of Application Server.) Figure 1 illustrates a cell in the midst of being upgraded from V5 to V6. Refer to this figure as we go through the features and complexities of this environment Figure 1. Mixed release cells in WebSphere Application Server V6 file:///C|/developerworks/pdf_0502/0502_cheng/0502_cheng.html (2 of 12) [2/23/2005 6:49:58 PM] IBM WebSphere Developer Technical Journal: System management for WebSphere Application Server V6 -- Part 2 Upgrading a cell The incremental upgrade process begins with the migration of your V5 deployment manager to V6. The deployment manager must always be the first part of the cell migrated to the new release level, and must always be at the highest release and fix level of any node within a cell to enable it to manage all the nodes in the cell, regardless of their individual release levels. To upgrade the deployment manager: 1. Make a backup of your Application Server V5 configuration. 2. Install Application Server V6 on the same machine where your V5 deployment manager is located. 3. Create a new V6 deployment manager profile. Ensure that the name of the cell and the name of the deployment manager node match your existing cell. 4. Shut down your V5 deployment manager. This should not affect your applications, as the deployment manager is not needed to keep your application servers running. 5. From the bin directory of your V6 deployment manager profile, run the WASPreUpgrade tool. file:///C|/developerworks/pdf_0502/0502_cheng/0502_cheng.html (3 of 12) [2/23/2005 6:49:58 PM] IBM WebSphere Developer Technical Journal: System management for WebSphere Application Server V6 -- Part 2 For example, if you are using a Microsoft® Windows® machine, run: .\WASPreUpgrade.bat where: is a temporary directory of your choosing, and is where you installed your V5 deployment manager. The WASPreUpgrade tool examines the V5 installation, and copies the files that it needs to recreate the V5 environment into . 6. From the bin directory of your V6 deployment manager profile, run the WASPostUpgrade tool. For a Windows machine, this would be: .\WASPostUpgrade.bat -profileName The WASPostUpgrade tool uses the contents of , created by the WASPreUpgrade tool, to populate the deployment manager profile, whose profile is , so that the configuration of the V6 deployment manager is the same as the V5 deployment manager. 7. Start the V6 deployment manager. After completing the above steps, you will have created a new V6 cell whose deployment manager manages all the pre-existing V5 nodes. All the V5 nodes in the cell remain unchanged and are unaware that they are being managed by a new deployment manager. The WASPostUpgrade tool also disables the old V5 deployment manager. This is to prevent starting two deployment managers that would simultaneously manage the same cell. If for some reason you want to immediately undo the upgrade: a. b. c. d. Stop the V6 deployment manager. Restore the backed up V5 deployment manager configuration. Restart V5 deployment manager. Remove the V6 deployment manager profile. Again, this is to prevent starting both V5 and V6 deployment managers together. It is not advisable to undo the upgrade after you have performed configuration changes through the new deployment manager. These changes are updated in the new deployment manager, which is separate and distinct from the old V5 deployment manager, and cannot be easily reintegrated back into the V5 cell. file:///C|/developerworks/pdf_0502/0502_cheng/0502_cheng.html (4 of 12) [2/23/2005 6:49:58 PM] IBM WebSphere Developer Technical Journal: System management for WebSphere Application Server V6 -- Part 2 After the deployment manager has been upgraded to V6, the individual nodes in the cell can be upgraded. To upgrade a node: Make a backup of the deployment manager configuration. Make a backup of the V5 node s configuration. Install Application Server V6 on the same machine as your node. Create a custom profile, one that is not pre-federated. This is a profile with minimal configuration that does not contain any server. Ensure the name of the node is the same as the node you are upgrading. 12. Ensure that your new V6 deployment manager is running and can communicate with the V5 node you are upgrading. 13. Stop the V5 node and all its servers. Your application should continue to run as long as each server on the node is a member of a cluster with additional members on other machines. 14. From the bin directory of the new V6 node s profile, run the WASPreUpgrade tool. For a Windows machine: .\WASPreUpgrade.bat where: is the temporary directory for WASPreUpgrade to store information about V5 node. is the location where the V5 node is installed. WASPreUpgrade examines the V5 node and copies the information it needs to upgrade the node to V6 into . 15. Again from the bin directory, run the WASPostUpgrade tool. For a Windows machine: .\WASPostUpgrade.bat -profileName where: is the same directory as the one used for WASPreUpgrade, and is the name of the profile used to create the node. 16. Start the V6 node and the application servers. WASPostUpgrade contacts the V6 deployment manager to upgrade the node in the master configuration repository to V6. After upgrading the configuration on the deployment manager, the local repository of the node is synchronized with the master copy from the deployment manager. WASPostUpgrade also disables the old node so that you cannot start both the new and the old node simultaneously. file:///C|/developerworks/pdf_0502/0502_cheng/0502_cheng.html (5 of 12) [2/23/2005 6:49:58 PM] 8. 9. 10. 11. IBM WebSphere Developer Technical Journal: System management for WebSphere Application Server V6 -- Part 2 If for some reason you need to immediately undo the upgrade: a. b. c. d. e. Stop the V6 node and application servers. Restore the deployment manager configuration you backed up in Step 8 Restore the node configuration you backed up in Step 9. Restart the V6 deployment manager, and the V5 node and servers. Delete the V6 node profile so that you cannot start both V5 and V6 nodes simultaneously. Configuration files As the incremental upgrade proceeds on each node, the cell's central configuration repository will contain documents for both V5 and V6 nodes. Configuration synchronization will ensure that configuration documents replicated to the V5 nodes are consumable by the V5 runtimes, even if the documents are stored on the deployment manager repository in V6 formats. Referring back to Figure 1, the deployment manager master repository stores all configuration files at the V6 level, but is designed to also accommodate V5 configuration information. When synchronizing the configuration file between the deployment manager and a V5 node, transformations are applied to the V6 format to make it V5-compatible. Some of these transformations include changing the namespaces in the XML files, removing configuration attributes that are new in V6, and stripping out resources not understood by the V5 runtime. JMX interoperability WebSphere Application Server V5 supports JMX 1.1, while V6 supports JMX 1.2. Due to the evolution of the JMX specification, the formats of serializables defined by the JMX specification, such as javax.management.ObjectName, are incompatible between Application Server V5 and V6. In order for the V6 deployment manager to manage a V5 node, Application Server V6 has enhanced the SOAP connector to be JMX-version aware. The RMI connector has not been enhanced, thereby restricting the JMX function between the V5 and V6 runtimes to SOAP connectors only. When sending a JMX-defined serializable to a V5 node, the SOAP connector runtime applies appropriate transformations to the JMX 1.2 serializable classes so that a JMX 1.1 serializable is received by the Application Server V5 runtime. Similarly, when receiving a JMX 1.1 serializable from the V5 runtime, it is transformed to the JMX 1.2 format, so that it is understood by the V6 runtime. The transformation framework employed by the SOAP connector uses special class loaders to perform these transformations. All classes defined by the JMX specification are currently being transformed. However, user-defined classes that refer to a JMX-defined class cannot be transformed correctly, and are not supported when passed between the V5 and V6 runtimes. For example, say you implemented a JMX MBean and wanted to pass a class you created as a parameter to one of its methods. This user-defined class is passed correctly, as long as it does not contain a file:///C|/developerworks/pdf_0502/0502_cheng/0502_cheng.html (6 of 12) [2/23/2005 6:49:58 PM] IBM WebSphere Developer Technical Journal: System management for WebSphere Application Server V6 -- Part 2 reference to one of the serializables defined by JMX, such as ObjectName. Note that passing ObjectName by itself works, but passing some class "A" that refers to ObjectName will not work. Expect to see few (if any) user defined classes fall into this category. If you need to define a new MBean method that works with both V5 and V6 releases, then pass any classes belonging to the javax.management package as separate parameters. Most of the internal classes within Application Server V6 that contain references to the javax.management package and are used as MBean method parameters have been transformed so that they work in the mixed release environment. The only exceptions are PMI-related classes. Users of PMI will have to wait for a maintenance release of Application Server V6 before they can receive PMI data correctly from V5 nodes to a V6 environment. The JMX 1.2 specification also disallows the use of ":" as a valid property value within an ObjectName. The V5 ObjectName contained ":" when it was used to store configuration IDs, but this has been changed in V6 to "|". The SOAP connector will automatically transform between these two characters, so that a configuration ID is transparently usable by both runtime versions. When using JMX from within an Application Server V5 runtime to call into V6, classes newly defined in V6 can not be deserialized in the V5 runtime, since these classes are not available in the V5 runtime CLASSPATH. This situation rarely occurs. But when it does, it is usually caused by a new exception introduced in V6. Adapt-A-View administration The Application Server V6 deployment manager is aware of information about the nodes it manages, including Application Server product version, operating system, and other product features. As a node is upgraded to a new version, or as product features are added, the node information is also updated. The deployment manager uses this node information to determine which administrative functions are actually valid for a given node. For example, new V6 features are not displayed on the console for a V5 node, since those new features are not valid for V5. When displaying a node or a server, a new column containing the node version is also displayed. This ability to adapt to different node information is called Adapt-A-View. For scripting users, the scripting runtime has also been enhanced with Adapt-A-View capabilities. Unlike the console, which can select what information to present to the user, the scripting runtime implements configuration validation. For example, if the user tries to configure a V5 node by creating a new instance of a configuration type, or by setting a new V6 configuration attribute, an exception will be raised. If the user tries to access types or attributes that are deprecated, a warning is logged, but the operation is allowed to proceed. One exception concerns the preexisting AdminConfig attributes command. Since the command itself does not take a version parameter, it will list all attributes that are valid for the file:///C|/developerworks/pdf_0502/0502_cheng/0502_cheng.html (7 of 12) [2/23/2005 6:49:58 PM] IBM WebSphere Developer Technical Journal: System management for WebSphere Application Server V6 -- Part 2 irrespective of the version. For those who want to write their own Adapt-A-View code, the node information can be accessed through a new set of Java APIs, documented in the WebSphere Application Server Information Center, and are also available through new wsadmin tasks. Here are some examples of the tasks: q q q q $AdminTask getNodeBaseProductVersion { -nodeName } returns WebSphere base product version, such as "6.0.0.0" $AdminTask getNodeMajorVersion { -nodeName } returns the WebSphphere base product major version, such as "6" $AdminTask getNodeMinorVersion { -nodeName } returns the WebSphere base product minor version, such as "0" $AdminTask getNodePlatformOS { -nodeName } returns the operating system of the node, such as "windows" Runtime interoperation In addition to JMX interoperability, other parts of the Application Server runtime have also been enhanced to ensure they work in a mixed environment. If you have a mixed cluster containing both old version and new version nodes, the workload management runtime will still route requests to all members of the cluster. However, in order for this mixed environment to work, certain V6 performance enhancements are not turned on by default. When all the members are upgraded to V6, the user is encouraged to set the com.ibm.websphere.ObjectIDVersionCompatibility ORB property to enable these performance enhancements. If you are working with JMS, interoperability between the old and new runtimes are preserved as well. You will, however, need to change your topic connection factory port settings from DIRECT to QUEUED prior to migrating your node. During migration, the jmsserver from V5 is converted to a regular application server, with appropriate message engine settings to perform the functions of the original JMS server. This happens because Application Server V6 contains a brand new JMS implementation using message engines. Similarly, the V5 WebSphere Default Messaging Provider has been renamed the V5 Default Provider to make room for the message engine based default provider. If you are using Data Replication Service (DRS), your existing configurations should continue to work. After migrating all the nodes, customers are encouraged to move to the new DataReplication domain, a new implementation in Application Server V6. Using resources Resources that are defined in Application Server V5 will continue to work after migrating to V6, including: q q JDBC provider Generic JMS provider file:///C|/developerworks/pdf_0502/0502_cheng/0502_cheng.html (8 of 12) [2/23/2005 6:49:58 PM] IBM WebSphere Developer Technical Journal: System management for WebSphere Application Server V6 -- Part 2 q q q q q WebSphere MQ JMS provider Mail provider Resource environment provider URL providers JCA 1.0 resource adapters JDBC provider. Of course, any resources new to V6 may not be created on V5 nodes or servers. These include: q q WebSphere default messaging provider JCA 1.5 resource adapters. Working with applications In Application Server V6, all applications are classified as either V5- or V6-compatible, based on the Application Server features they use: q q V5-compatible applications are those that deploy and run within a V5 environment. These include J2EE 1.3 applications and JCA 1.0 adapters, and do not call any new V6 APIs. V6-compatible applications are those applications that only run within a V6 environment, and include J2EE 1.4 applications, JCA 1.5 adapters, and any applications that call new APIs introduced in V6. A V5-compatible application may be installed on any V5 or V6 server, or on any cluster containing V5 or V6 servers. When updating an application for re-installation, or for editing or remapping modules to new targets, the target of the V5-compatible application is not restricted. By contrast, the target of a V6compatible application may only be a V6 server, or a cluster containing only V6 members. Application Server checks for version compatibility based on the J2EE or JCA version of the application; it does not check any of the APIs that the application is using. What this means is that Application Server will let a J2EE 1.3 application that calls new V6 APIs -- though it is not V5compatible -- deploy to a V5 server or cluster. Enforcing lower-level checks would be too costly during application installation or updates, for the very few cases that may occur. When installing a V5-compatible application to a V5 target, the deployejb, deployws, and precompileJSP options are not supported. The deployment tool in V6 is currently not aware of the target environment in which the applications are deployed, so these applications need to be predeployed before installation. The useMetadataFromBinary option is also not supported when installing to a V5 target. This option is turned off by default since it is rarely used. The reason for this restriction is that the metadata in the application binaries have been enhanced in V6; the version in the deployed applications is for the V6 runtime and cannot be consumed by the V5 runtime. Administrators are encouraged to deploy, edit, or update their applications from a V6 environment. If initiated from a V5 environment (for example, by starting wsadmin from a V5 node to point to the V6 file:///C|/developerworks/pdf_0502/0502_cheng/0502_cheng.html (9 of 12) [2/23/2005 6:49:58 PM] IBM WebSphere Developer Technical Journal: System management for WebSphere Application Server V6 -- Part 2 deployment manager), only those tasks available in V5 are supported. For example, the following V6 application deployment tasks are not supported: q q q Mapping message destination reference to EJB Binding J2CObject to JNDI name Binding J2CActivation to destination JNDI name Capacity planning: Working with nodes, servers and clusters There are restrictions with regard to what can be done with V5 nodes. These restrictions have to do with the inability to expand the capacity of a mixed release cell by adding additional nodes, servers, or cluster members. These restrictions will be lifted in future maintenance releases for V5 or V6 where appropriate. In the meantime, the workaround is to preplan the post-migration capacity by creating additional nodes and servers prior to upgrading the cell from V5 to V6. These additional nodes and servers do not have to be started until needed. Workarounds for other specific situations are presented below: q q q q A V5 node may not be added to a V6 cell. One workaround is to first upgrade the node to V6, then add the node to the V6 cell. A V5 node may not be removed from a V6 cell. There are two workarounds. First, you can uninstall the V5 node, then run the cleanupNode command to delete the node from the V6 deployment manager. Second, you can upgrade the V5 node, then run the removeNode command. A new V5 server may not be created after the deployment manager is upgraded to V6. A future release of Application Server will enable this function by supplying the required V5 templates and runtime changes. A V5 server cannot be converted to a cluster, nor can a new V5 member be added to a cluster. A workaround is to first upgrade the node to V6 before the conversion or expansion. Once a cluster contains a V6 member, it becomes a mixed cluster. Adding new V6 members to a mixed cluster is supported. Scripting compatibility In Application Server V6, changes were made to some configurations that rendered them incompatible with V5. Although efforts were made to maintain strict compatibility, there are a few areas in which it is better to make a clean break early so that future configuration tasks will be easier. Where an incompatibility exists in V6, the runtime can nevertheless run in "compatibility" mode, meaning that the V6 runtime can tolerate both the old and new configuration settings. Scripts developed in V5 may also be used to configure both V5 and V6 nodes/servers. V6 nodes and servers that are migrated from V5 are done so with compatibility mode turned on, the migration tool default. Compatibility mode is good for the initial upgrade of the cell, when all the members of the cell started file:///C|/developerworks/pdf_0502/0502_cheng/0502_cheng.html (10 of 12) [2/23/2005 6:49:58 PM] IBM WebSphere Developer Technical Journal: System management for WebSphere Application Server V6 -- Part 2 from V5. Compatibility mode is not applicable to new V6 nodes that are added to the cell, since these brand new nodes and servers are created with the new configurations. Therefore, the recommendations are: q q q If no new V6 node is to be added to the cell after migrating the deployment manager, the entire cell may be run in compatibility mode. If the entire cell is to be upgraded before any new V6 nodes are added, modify your existing scripts as soon as possible after migration to use the new configuration. After the script is modified, run the convertScriptCompatibility tool to move from the old to the new configuration. Another alternative is to modify the existing scripts prior to migration and run the migration tool with compatibility mode off. If a mixed environment consisting of mixed version nodes from a V5 cell and new V6 nodes is needed, then the existing scripts must be written to be version aware (see Adapt-A-View section on the node information APIs): r Use the old format when operating on the V5 node. r Use the new format when operating on the V6 node. Nodes can be migrated from V5 to V6 with compatibility mode off. Alternatively, if they are migrated with compatibility mode on, the convertScriptCompatibility tool can then be used to move to the new configuration. One incompatible change between releases is in the HTTPTransport used to specify the Web container port. In V6, this has been replaced by a channel framework based configuration, which is a much more flexible mechanism for supporting the input and output of transport end points. However, moving to the channel framework necessitates that the host and port settings for the Web container be changed to conform to channel definitions. A second incompatible change is in the use of processDefinitions rather than processDefinition. This is a result of the integration with WebSphere Application Server for z/OS® to support a single cell consisting of both workstation and Z nodes. On workstation, there is only one processDefinition per server; on Z, there can be multiple. Therefore, processDefinitions is used to accommodate both. Another incompatible change is in the location of the transaction log. In Application Server V5, this was specified via TransactionService. For Application Server V6, this is specified as an attribute on ServerEntry. This change was introduced to enable peer recovery of transaction log to complete indoubt transactions when the machine hosting the transaction log crashes. One reason that compatibility cannot always be strictly preserved is that the configuration model currently made available to end users is specified at a very low level, which in turn triggers changes in the implementation. In future versions of Application Server, more high level wsadmin tasks will be introduced so that administrators can work with a higher level conceptual model that more closely relate to the tasks at hand, and that are less susceptible to changes in the underlying implementation. file:///C|/developerworks/pdf_0502/0502_cheng/0502_cheng.html (11 of 12) [2/23/2005 6:49:58 PM] IBM WebSphere Developer Technical Journal: System management for WebSphere Application Server V6 -- Part 2 Continuous enhancements in usability will be characteristic of forthcoming versions of WebSphere Application Server. Conclusion This article described the incremental cell upgrade process, with its nuances, complexities, restrictions, and implications for the administrator. Administrators who wish to upgrade an entire cell quickly will find that upgrading the cell one node at a time is a significant improvement over having to either shut down the entire cell, or create a parallel cell. Administrators with the additional requirement of running V5 nodes in a mixed cell environment for extended periods of time will have to work around certain restrictions, the most serious being the capacity planning issues. Many of these temporary restrictions will be removed with future versions or maintenances releases of WebSphere Application Server. Resources q System Management for WebSphere Application Server V6 -- Part 1: Overview of system management enhancements WebSphere Application Server V6 Migration Guide Get involved in the developerWorks community by participating in developerWorks blogs. Purchase WebSphere books at discounted prices q q q About the author Michael Cheng is a Senior Software Engineer at the IBM Software Development Lab in Austin, Texas. He is currently one of the technical leads for WebSphere Application Server System Management. file:///C|/developerworks/pdf_0502/0502_cheng/0502_cheng.html (12 of 12) [2/23/2005 6:49:58 PM] IBM WebSphere Developer Technical Journal: Building an Enterprise Service Bus with WebSphere Application Server V6 -- Part 2 IBM WebSphere Developer Technical Journal: Building an Enterprise Service Bus with WebSphere Application Server V6 -- Part 2 Business requirements and the bus Level: Intermediate Rachel Reinitz (rreinitz@us.ibm.com), Senior Consulting IT Specialist , IBM Andre Tost (atost@us.ibm.com), Senior Technical Staff Member, IBM 23 Feb 2005 This is Part 2 in a series of articles that describe how to use the new messaging engine in IBM® WebSphere® Application Server V6 to build an Enterprise Service Bus (ESB), a crucial piece of SOA infrastructure. This article describes a sample business case for building an ESB with WebSphere V6 Messaging Resources, and explains the steps for setting up an instance of the bus. Contents: Introduction The business problem The technical environment Basic setup Setup for Web services Conclusion Resources About the authors Rate this article Related content: IBM WebSphere Developer Technical Journal Introduction In Part 1 of this series, we introduced the core concepts of the WebSphere V6 Messaging Resources that can be used to build an Enterprise Service Bus (ESB). In Part 2, we present a business scenario with requirements that lead to building Part 1: Introduction to WebSphere V6 Messaging an ESB, and also cover the steps to create an instance of the "bus" and set it up Resources for use with Web services. We will use this business scenario to provide a realistic context throughout this article series. The business problem Our fictional company, which we will call "Posts-R-US," provides package shipping services, including: q q q q Consumer shipping (competing with the post office). Contracted shipping for businesses. OEM shipping (for example, for an online retailer). Guaranteed delivery with optional acknowledgements. Posts-R-US has grown quickly. The company recently purchased a European company, "EurPosts", and needs to integrate EurPosts systems with the Posts-R-US systems. With their direct online presence, stores, storing areas, delivery crews, airplane systems, and OEM, they have a need to serve a variety of different types of clients. To lower costs, remain competitive, and improve their customers' experiences, Posts-R-US needs to improve the integration of their disparate systems. Currently, when a new application is developed or a new system is incorporated, extensive point-to-point integration across many technologies is required. Hence, they have decided to develop an ESB as a core component of improving their integration. Posts-R-US is also going to file:///C|/developerworks/pdf_0502/0502_reinitz/0502_reinitz.html (1 of 9) [2/23/2005 6:50:03 PM] IBM WebSphere Developer Technical Journal: Building an Enterprise Service Bus with WebSphere Application Server V6 -- Part 2 improve their business process automation and flexibility through the use of Business Process Execution Language (BPEL) and associated tooling (see Resources). Figure 1 shows an overview of some of the systems that Posts-R-US needs to integrate with each other. Figure 1. Systems requiring integration The technical environment Key clients and systems of Posts-R-US utilize a variety of technologies including WebSphere MQ, Web services, EJB™ components, .NET® clients, publish/subscribe, CICS® legacy systems, databases, SAP®, and other third party applications. The systems shown in Figure 1 are implemented with a variety of technologies, thus adding an enterprise service bus simplifies the integration across these many technologies. Figure 2 shows an example of the technologies used in Posts-R-US' business that need integration, and how an ESB simplifies the connections required. Figure 2. Required connections simplified using ESB file:///C|/developerworks/pdf_0502/0502_reinitz/0502_reinitz.html (2 of 9) [2/23/2005 6:50:03 PM] IBM WebSphere Developer Technical Journal: Building an Enterprise Service Bus with WebSphere Application Server V6 -- Part 2 The examples in subsequent installments in this article series will be based on the business systems and technologies shown in Figure 2, and will show how WebSphere Application Server V6 can be used to build an ESB that meets the integration requirements for this company. We will not cover in detail the architectural aspects of building an ESB and how it enables good integration; we will focus instead on implementation considerations. The next section goes through the basic setup that is needed to create an enterprise service bus with Web services capability. Basic setup As the very first step, we will create a system integration bus (SIB or SIBus) and assign it to an instance of WebSphere Application Server. We will then enable the bus to use Web services as a protocol. Create a bus To create a Bus instance: 1. Open the WebSphere Application Server admin console (the server must be running). 2. In the left navigation pane, select Service Integration => Buses. 3. Select Buses, then in the following dialog, select New, which starts the wizard to create a bus. 4. Name the new bus, TheBus and select OK. 5. Save your changes, then see the new bus in the list (Figure 3). Figure 3. New bus in WebSphere Application Server admin console Assumptions The instructions in this section assume a default installation of a standalone WebSphere Application Server. Your default profile will be named "default" if using WebSphere Application Server Base and "AppSrv01" if using WebSphere Application Server Network Deployment (ND). The instructions assume that the server is "server1" and node name is "node1". To setup a command window for the profile: 1. Change to the /profiles//bin directory. 2. Setup the command window for this profile by file:///C|/developerworks/pdf_0502/0502_reinitz/0502_reinitz.html (3 of 9) [2/23/2005 6:50:03 PM] IBM WebSphere Developer Technical Journal: Building an Enterprise Service Bus with WebSphere Application Server V6 -- Part 2 executing the setupCmdLine.bat. Add a bus member A bus needs to be assigned to run on one or more application servers and server clusters. For most development activity, you will create and assign a single bus member to the bus. When a bus member is added, a messaging engine is created in that WebSphere instance, which has its own data store for messages. For our purposes, we will have one bus with only one bus member which is a single instance of WebSphere Application Server: 1. 2. 3. 4. 5. Select TheBus. In the next dialog, select Bus Members, then Add. Make sure that the Server radio button is selected. From the server selection box, select node1:server1, which will likely be selected by default. Click Next and Finish, then save your changes. You now have a WebSphere Messaging Resources bus ready for use. Setup for Web services WebSphere Messaging Resources requires some setup to enable the bus to be able to receive Web service requests, to convert messages into SOAP messages in mediations, and to send Web service requests. The Web services feature of the Service Integration Bus is referred to as SIBWS in the WebSphere Application Server V6 Information Center (see Resources). As we described in Part 1, WebSphere Messaging Resources convert all incoming messages into Service Data Objects (SDO). An SDO repository is used to store WSDL definitions and the SIBus uses those definitions as part of the Web services support. Therefore, the first thing you need to do is create this SDO repository. Additionally, for the bus to receive Web service requests from clients, the bus needs to be configured with endpoint listeners; as their name implies, endpoint listeners listen on specific ports for incoming Web services file:///C|/developerworks/pdf_0502/0502_reinitz/0502_reinitz.html (4 of 9) [2/23/2005 6:50:03 PM] IBM WebSphere Developer Technical Journal: Building an Enterprise Service Bus with WebSphere Application Server V6 -- Part 2 messages. There are endpoint listeners provided for SOAP over HTTP and for SOAP over JMS. To enable the bus to send Web service requests, the bus must be configured with a resource adapter. (In a later article, we will explain how to configure the bus to accept incoming Web services requests, called inbound services, and send Web service requests, called outbound services.) Install SDO repository The SDO repository can use the IBM Cloudscape® database which is automatically installed as part of your WebSphere Application Server installation, or you can configure it to use a database of your choosing. Provide the -createDb flag as part of the setup command to use Cloudscape. To install the SDO repository: 1. In a command window, change to the /bin directory, then execute: wsadmin -f installSdoRepository.jacl -createDb node1 server1 2. In the WebSphere admin console, under Enterprise Applications, you should now see a new application, called SDO Repository, successfully started. Any future configuration of Web services will now store the appropriate definitions in the SDO repository, without requiring any further setup. Typically, you will never deal with this repository directly. Install SIbus Web services resource adapter For the bus to act as a Web service requestor, sending Web service messages to providers, it must be configured with a resource adapter. A script included in the file sibwsInstall.jacl is provided with WebSphere Application Server for setting up the SIBWS application (described in the next section) and installing the resource adapter: 1. In a command window, change to the /bin directory and execute: wsadmin -f ../util/sibwsInstall.jacl INSTALL_RA -installRoot "C:/Program Files/IBM/WebSphere/AppServer" -nodeName node1 2. You should see this message: The resource adapter has started successfully : SIB_RA. Install and configure endpoint listeners Endpoint listeners need to be installed and configured for each protocol you want to use to receive Web service requests into the bus. For these endpoint listeners to work, you need to install the SIBWS application as well. The same script we used to install the resource adapter, sibwsInstall.jacl, is used for installing the endpoint listeners, just with different parameters. After the installation, additional configuration in the admin console is required for each endpoint listener. Be sure to create the bus and install the resource adapter before installing the SIBWS application and endpoint listeners. Two endpoint listeners are provided for each protocol. You can use one for requests coming from external clients into the bus, and the second one for requests coming from internal clients. You can configure security differently for each listener. If you have global security enabled, no users will be able to access any inbound service. Instructions are provided in the WebSphere Application Server V6 Information Center on how to configure the security settings to allow access. file:///C|/developerworks/pdf_0502/0502_reinitz/0502_reinitz.html (5 of 9) [2/23/2005 6:50:03 PM] IBM WebSphere Developer Technical Journal: Building an Enterprise Service Bus with WebSphere Application Server V6 -- Part 2 To install the SIBWS application: 1. In a command window, change to the /bin directory, and execute: wsadmin -f ../util/sibwsInstall.jacl INSTALL -installRoot "C:/Program Files/IBM/WebSphere/AppServer" -serverName server1 -nodeName node1 2. In the WebSphere Application Server admin console, under Enterprise Applications, you should now see a new application, called sibws.node1.server1, successfully started. For this application to start successfully, the resource adapter must have been installed first. (The name of this application may differ in your environment based on the node and server names that you picked during installation.) 3. For each supported Web services protocol (such as, HTTP or JMS), install two endpoint listener applications using the sibwsInstall.jacl script. For example, to install the HTTP endpoint listener applications, execute: wsadmin -f ../util/ sibwsInstall.jacl INSTALL_HTTP -installRoot "C:/Program Files/IBM/WebSphere/AppServer" -serverName server1 nodeName node1 4. In the admin console, under Enterprise Applications, you should now see the two new applications listed, called sibwshttp1.node1.server1 and sibwshttp2.node1.server1. Both should be successfully started. Your Enterprise Applications window in the WebSphere Application Server admin console should now look like Figure 4. Figure 4. Enterprise Applications in admin console file:///C|/developerworks/pdf_0502/0502_reinitz/0502_reinitz.html (6 of 9) [2/23/2005 6:50:03 PM] IBM WebSphere Developer Technical Journal: Building an Enterprise Service Bus with WebSphere Application Server V6 -- Part 2 5. Now that the code for the listener is installed, we will create the specific endpoint listener. Navigate to Servers => Application Servers => server 1 => Endpoint Listeners and select New. 6. Enter the field values listed below (and in Figure 5); these values are very specific -- the names and values must match those specified in the Endpoint listener configuration details section of the WebSphere Application Server V6 Information Center: r Name: SOAPHTTPChannel1 (this specific name is required) r URLRoot: http://localhost:9080/wsgwsoaphttp1/ r WSDL Serving HTTP URL root: http://localhost:9080/wsgwsoaphttp1/ 7. Click OK, then save your changes. Figure 5. Endpoint Listener configuration file:///C|/developerworks/pdf_0502/0502_reinitz/0502_reinitz.html (7 of 9) [2/23/2005 6:50:03 PM] IBM WebSphere Developer Technical Journal: Building an Enterprise Service Bus with WebSphere Application Server V6 -- Part 2 8. Configure the new endpoint listener to connect to our bus by selecting the new Endpoint Listener, SOAPHTTPChannel1, then Connection Properties. 9. Click New, and select your bus, TheBus. 10. Click OK and save your changes. 11. Go to TheBus => Destinations. There should be a new destination called node1.server1. SOAPHTTPChannel1. This new destination is where all messages arriving through the defined endpoint are routed. In other words, all of the incoming SOAP/HTTP Web services requests will now go to the SOAPHTTPChannel1 destination. Conclusion In this article, we described a business scenario for building an Enterprise Service Bus with WebSphere Application Server V6 Messaging Resources. We created our bus and set it up for use with Web services. In Part 3, we will start developing our enterprise bus, and begin fulfilling our scenario requirements by developing a client to send a confirmation message over JMS onto the bus, and then onto a message-driven bean. Resources q IBM Web site for Enterprise Service Bus file:///C|/developerworks/pdf_0502/0502_reinitz/0502_reinitz.html (8 of 9) [2/23/2005 6:50:03 PM] IBM WebSphere Developer Technical Journal: Building an Enterprise Service Bus with WebSphere Application Server V6 -- Part 2 q BPEL articles WebSphere Application Server Version 6.0 Information Center Redpaper: WebSphere Application Server V6 Technical Overview Get involved in the developerWorks community by participating in developerWorks blogs. Purchase Web Services books at discounted prices. q q q q About the authors Rachel Reinitz is a Senior Consulting IT Specialist with IBM Software Services for WebSphere focusing on Web services. Rachel consults with customers and ISVs on how service oriented architecture and Web services can be used to achieve their business and technical objectives. She developed IBM's Advanced Web Services Training course and is a frequent conference presenter. Rachel is also an experienced eXtreme Programming coach who has used XP practices for 4 years. She lives in the Bay Area in California, and enjoys hiking, socializing, and international travel. Andre Tost works as a Senior Technical Staff Member in the WebSphere Business Development group, where he helps IBM's Strategic Alliance partners integrate their applications with WebSphere. His special focus is on Web services technology throughout the WebSphere product family. Before his current assignment, he spent ten years in various development and architecture roles in IBM software development, most recently for the WebSphere Business Components product. Originally from Germany, he now lives and works in Rochester, Minnesota. In his spare time, he likes to spend time with his family, and play and watch soccer whenever possible. file:///C|/developerworks/pdf_0502/0502_reinitz/0502_reinitz.html (9 of 9) [2/23/2005 6:50:03 PM] IBM WebSphere Developer Technical Journal: Using the Java Secure Socket Extension in WebSphere Application Server IBM WebSphere Developer Technical Journal: Using the Java Secure Socket Extension in WebSphere Application Server What is the JSSE all about? Level: Intermediate Messaoud Benantar (mbenanta@us.ibm.com), WebSphere J2EE Consultant, IBM Software Services for WebSphere Keys Botzum, Senior Consulting I/T Specialist, IBM Software Services for WebSphere 23 Feb 2005 This article addresses the configuration of the IBM® JSSE (Java™ Secure Socket Extension), discusses aspects of keystore and truststore, and offers recommendations for handling these important elements of the JSSE in the IBM WebSphere® Application Server environment. Introduction Java Secure Socket Extension (JSSE) is a Java standard encapsulating the low level programming interfaces to the Secure Socket Layer (SSL) protocol and its corresponding standard Transport Layer Security (TLS) protocol. IBM JSSE is the Java implementation of the JSSE framework. It supports SSL V2 and V3 and TLS V1. JSSE is architected such that it provides for two sets of interfaces: one is referred to as the Service Provider Interface (SPI) and the other one is an Application Programming Interface (API). Those who provide implementation-specific function plugs use the provider interface (essentially, the plug into the interface). Application programmers generally deal only with the API. They can write portable code that depends only upon the methods that are exposed in the standard public APIs. The IBM JSSE implementation includes the IBM JSSE cryptographic providers as well. It is important that developers adhere to the best programming practices in order to enable application portability. The JSSE API can be portable as long as the use of provider-specific information is not embedded or hardcoded in the application. IBM makes no claim of interoperability with other JSSE providers. No formal testing has been performed by the IBM development laboratory. Contents: Introduction Configuring and installing the IBM JSSE: Do I need to do anything? Truststore and keystore: What are they and why do I care? How to use SSL when the target application is exposed via a URL Client side JSSE socket programming Can I use multiple keystores/truststores simultaneously? HTTPS with multiple keystores Conclusion Resources About the authors Rate this article Related content: IBM WebSphere Developer Technical Journal The intent of separating the API and SPI interfaces is to shield applications from the provider so that portability can be achieved. The functionality provided by each provider, however, may not necessarily match functionality provided by others. While the IBM JSSE includes IBM's providers, other vendors have their own providers. When using WebSphere Application Server, for example, we are focusing on IBM's own providers. Therefore, application code that assumes any particular provider is not portable. One common example of this is application code that explicitly loads com.sun.* classes. Since com.sun.* is not part of JSSE (or J2SE for that matter), such code is not portable. As you develop your code you should work hard to avoid provider-specific dependencies. Our examples here demonstrate that approach. Programming to the JSSE is made simple in large part due to the high level abstractions that it provides around the standard socket programming interface. This makes it easy to establish network connections between two end-points that wish to communicate using transport level security over the TCP/IP protocol. The security services provided by JSSE consist of the transport-level message integrity and confidentiality (encryption), server authentication, and optional client authentication. file:///C|/developerworks/pdf_0502/0502_benantar/0502_benantar.html (1 of 12) [2/23/2005 6:50:09 PM] IBM WebSphere Developer Technical Journal: Using the Java Secure Socket Extension in WebSphere Application Server In this document, we address the configuration of the IBM JSSE, discuss the keystore and truststore aspects, and make recommendations for handling these important elements of the JSSE in the WebSphere Application Server environment. Subsequently, we present the JSSE programming model and show how simple it is when accessing resources available over HTTPS. Finally, we show how multiple keystores/truststores can be used simultaneously in a single application. Configuring and installing the IBM JSSE: Do I need to do anything? WebSphere Application Server V5 (and later) and WebSphere Studio V5 ship with ibmjsse.jar (which supports JSSE version 1.0.3) and its related certpath.jar. IBM JSSE is, therefore, automatically available for use by applications running in the WebSphere Application Server environment. To reiterate, WebSphere Application Server includes JSSE and fully supports it out of the box. No further install is required on your part; in fact, replacing JSSE or JCE implementations from other sources is forbidden. (You cannot override core runtime function. You can, of course, have additional providers, but don't replace what is already there). You do need to make sure that JSSE and its supporting JAR files, such as certpath.jar, are on your classpath during development (they are always on the classpath during run time). certpath.jar is a package that contains certificate path construction and validation functions needed by the JSSE runtime in order to establish certificate trust paths. You not need to program to the certpath.jar APIs to establish SSL/TLS communication channels, but JSSE will use it. SSL was developed by Netscape Communications Corporation in 1994, while TLS V1.0 is a standard defined by the Internet Engineering Task Force (IETF) that is based on SSL V3.0, with slight differences in the way cryptographic algorithms are used. For instance, while SSL uses the Message Authentication Code (MAC) algorithm to produce an integrity check value, TLS applies a keyed Hashing for Message Authentication Code (HMAC) algorithm. IBM JSSE provides the JSSE functionality for your WebSphere Application Server environment and deployed applications. This is statically set in the java.security configuration file in the JDK directory under your WAS install path. The following is the list of default providers listed out of the box in your java.security file on a Windows® system. Note that the names of the providers remain the same across platforms; the ordering, however, may be different. Regardless of platform, your out-of-thebox JSSE provider for WebSphere Application Serer is IBMJSSEProvider. # # List of providers and their preference orders # security.provider.1=sun.security.provider.Sun security.provider.2=com.ibm.crypto.provider.IBMJCE security.provider.3=com.ibm.jsse.IBMJSSEProvider security.provider.4=com.ibm.security.cert.IBMCertPath security.provider.5=com.ibm.crypto.pkcs11.provider.IBMPKCS11 There is no need for you to change any of these. If you are curious, there are a number of providers here, most of which are not related to JSSE. The only JSSE-related providers are the IBMJSSEProvider, IBMJCE, and IBMCertPath. The latter two are used implicitly by the IBMJSSEProvider for certificate manipulation and encryption. Truststore and keystore: What are they and why do I care? The SSL protocol is based on public-key cryptography where encryption keys come in pairs that are mathematically related, but one cannot be deduced from knowing the other. The pair consists of the private key and the public key (private, public). The private key remains under the protection of the entity to which it belongs. Note that the owner really owns the pair, but the public key, as its name suggests, can be publicly known, or at least is freely disseminated to the entities that communicate with the owner of the public/private key pair. The security services that public key cryptography enable are based on the fact that a message encrypted using the public key can only be decrypted by the corresponding private key, and vice versa. Thus, if one encrypts a message using the public key of an entity, then it is guaranteed that only the entity can decrypt the message. An immediate question that comes to mind is how to be assured that the public key being used is indeed bound to a legitimate entity and not to someone else. That is where Public Key Infrastructures (PKI) comes into play (see Resources). file:///C|/developerworks/pdf_0502/0502_benantar/0502_benantar.html (2 of 12) [2/23/2005 6:50:09 PM] IBM WebSphere Developer Technical Journal: Using the Java Secure Socket Extension in WebSphere Application Server Figure 1. The relationship between client and server truststore/keystore Public Keys are distributed in containers called public key certificates (PKC). These are data constructs digitally signed by some signer (typically a Certificate Authority, but public keys can be self-signed). A digital signature stamps a proof of origin authenticity. One point to remember is that trust in computer security must be computationally verifiable. In order to verify that a public key certificate is legitimate, I need to verify the signature of the signer that issued it. This process is, in turn, based on the public key of the signer. This is where the truststore comes into play. When using JSSE for SSL communication, one needs to maintain the set of trusted signer certificates in a local store, hence the name truststore. The truststore on the client side, for example, is used by the JSSE runtime in order to verify that a client attempting to connect to a server is indeed interacting with a server with a legitimate certificate (one that is issued by a trusted signer). Therefore, the signer of the server certificate must have a PKC stored in the truststore of the client. Figure 1 illustrates the relationship between client and server truststore/keystore. By the same token, the server must have its private key locally protected and make it accessible to the JSSE runtime. That's where the keystore comes into play. A keystore has the same format as a truststore, it just contains different keys. In fact, the generic term "keystore" is typically used to mean "truststore or keystore." In summary, truststores contain certificates for the signers that are trusted in the environment where the truststore is used. A keystore, on the other hand, maintains the private key of an entity, as well as its corresponding PKC. For example, when a server authenticates itself to the client, it needs to retrieve its private key from its keystore in order to engage in an SSL handshake with the client. So, one should really care about what signers to trust; that is, the content of the truststore being used. The IBM-provided default truststore includes several well known and widely trusted Certificate Authorites (CA). One good practice here is to periodically browse through your truststore and make your own judgment about the trustworthiness of its content -- and possibly remove some CAs. Now that we know what a truststore is and what a keystore is, let's look at how they are defined in the WebSphere Application Server environment using the IBM JSSE. How to specify the keystores and truststores To open JSSE connections, you must have appropriate certificates and private keys in a truststore and keystore. You will need to configure the JVM to use your truststore or keystore. However, if you are performing only server authentication (that is, the client validates the server's certificate, but not the reverse), you will need only a truststore. When you create an SSL connection without specifying a truststore or a keystore explicitly, the JSSE runtime will use the file:///C|/developerworks/pdf_0502/0502_benantar/0502_benantar.html (3 of 12) [2/23/2005 6:50:09 PM] IBM WebSphere Developer Technical Journal: Using the Java Secure Socket Extension in WebSphere Application Server "default" stores. In the case of WebSphere Application Server, this means the cacerts file is used as a default truststore (it is located in java/jre/lib/security under the WAS install directory). If the site you are contacting uses a certificate issued by a well known CA, it is likely that the IBM provided default certificates contain the information you need already. You can determine what certificates are included with the JDK by using the iKeyman tool provided by IBM (automatically available for use after WebSphere Application Server is installed) to open the cacerts file. If the site you are accessing does not use a certificate from a CA that is included with WebSphere Application Server, you will need to obtain their signing certificate and add it to a truststore. We recommend that you not modify the existing JDK files, but instead create a new truststore using iKeyman. You will then need to configure the WebSphere Application Server runtime to use this truststore. To configure WebSphere Application Server to use a custom truststore, you need to set the JVM System property javax.net.ssl.trustStore. To set this JVM variable in WebSphere Application Server using the admin console: 1. From the admin console, navigate to Servers => Application Servers => server_name => Custom Properties => New. 2. Enter the Name of the property, which is: javax.net.ssl.trustStore. 3. Enter the value of the property, which is the fully qualified file name for your truststore. 4. Add the description if you wish. 5. Similarly, define an accompanying property that maintains the password needed to access your truststore by navigating to Servers => Application Servers => server_name => Custom Properties => New. 6. The property name is: javax.net.ssl.trustStorePassword with the value being the password. (Note here that the password remains in the cleartext.) 7. The keystore can be defined in the same way using the property javax.net.ssl.keyStore and its corresponding javax.net.ssl.keyStorePassword. You can also hardcode these properties in your application, as shown in the example below, but this is not a good practice, since it has the potential of limiting your application portability besides needing to browse your code to determine the values of these properties: System.setProperty("javax.net.ssl.trustStore", "yourTrustStoreFile"); System.setProperty("javax.net.ssl.trustStorePassword", "yourPassword") System.setProperty("javax.net.ssl.trustStorePassword", "yourPassword") System.setProperty("javax.net.ssl.keyStore", "yourKeyStoreFile"); For most situations, this configuration is sufficient. In rare cases, you may need more than just a single default truststore/keystore. Later, you will see how to specify your truststores and keystores to the JSSE runtime programmatically, and how to use multiple truststores and keystores within your application. Truststore search order You have seen that you can either rely on the default cacerts file, or you can define your own truststore. It may interest you to know how the JVM searches for truststores. When a truststore is needed, it is searched for in the following order until a match is found: file:///C|/developerworks/pdf_0502/0502_benantar/0502_benantar.html (4 of 12) [2/23/2005 6:50:09 PM] IBM WebSphere Developer Technical Journal: Using the Java Secure Socket Extension in WebSphere Application Server 1. If a truststore is defined programmatically through the Java API (discussed above), then it is the one that is used as the truststore. 2. If the javax.net.ssl.trustStore system property is defined, then the value of this property is used as the truststore's location. 3. If file lib\security\jssecacerts is defined off the java\jre directory, then the jssecacerts file is used as the truststore. (WebSphere Application Server does not ship with jssecacerts. We mention it for completeness only, so you may ignore this case.) 4. If file lib\security\cacerts is defined off the java\jre directory, then the cacerts file is used as the truststore. If a particular trust store is found, then the search stops and the found file becomes your truststore. For instance, if one specifies a truststore by using its Java System property, if a valid signer is not found in the truststore, search will not continue on afterward. What if I need to use my own truststore or keystore? WebSphere Application Server ships with a utility program called iKeyman which is automatically available for use after the WebSphere Application Server is installed. It is located in the bin directory underneath your WAS Install Root. (Refer to iKeyman documentation shipped with WAS for detailed information on how to use this utility, and Resources.) In a nutshell, iKeyman manages keystores. Keystores come in one of several formats and iKeyman supports the most common formats, including the Java Key Store, known as JKS, which is the "normal" format used with Java applications (in fact, the cacerts truststore is in that format). Next, we will see a simple example of using iKeyman to create a self-signed certificate. This is appropriate if the party you are communicating with will use the same certificate. If they already have their certificate, you will need to import the existing signing certificate, as mentioned earlier. To start this process, execute the iKeyman tool by running ikeyman.bat (on Windows platforms). The tool displays a graphical interface that looks like Figure 2. Figure 2. iKeyman GUI file:///C|/developerworks/pdf_0502/0502_benantar/0502_benantar.html (5 of 12) [2/23/2005 6:50:09 PM] IBM WebSphere Developer Technical Journal: Using the Java Secure Socket Extension in WebSphere Application Server To generate a keystore that contains, for example, a self-signed certificate: 1. 2. 3. 4. 5. 6. 7. Select Key Database File => New. Make sure that Key database type is JKS for Java Key Store. Enter the File Name and its Location (give .jks to your file), then select OK. Fill in the password value (no major password checking rules apply here), then OK. Click on Create, then select New-Self-Signed Certificate. Enter the desired certificate information, then OK. At this point, your keystore contains your private key as well as your public key certificate. Highlight your keystore file name, then select View/Edit. You should see something like Figure 3. Figure 3. Key information file:///C|/developerworks/pdf_0502/0502_benantar/0502_benantar.html (6 of 12) [2/23/2005 6:50:09 PM] IBM WebSphere Developer Technical Journal: Using the Java Secure Socket Extension in WebSphere Application Server You can use iKeyman to create a new self-signed certificate as we've just shown, or add a CA certificate to your own truststore. While we won't cover it here, if you wish to use iKeyman to add a new certificate to a keystore, remember that iKeyman can import certificates from a file in either binary DER format or in base64 ARM format. (DER stands for Distinguished Encoding Rules, a standard for data encoding, and ARM is the ASCII-armored-64 format.) How to use SSL when the target application is exposed via a URL Next, we will show a simple example of how to use JSSE to connect over HTTPS to a remote server. In this example, we'll assume that the already existing truststore contains the needed certificate information. The steps below summarize the actions required to make it possible for WebSphere Application Server server side code to act as a HTTPS client to another remote server. Configure JVM properties needed for JSSE and HTTPS Through JVM configuration, add com.ibm.net.ssl.internal.www.protocol as the Java protocol handler. By default, no handler is set, so this step is required. It is best to define this as part of your JVM properties instead of hardcoding it in your application. Follow the same instructions for defining the keystore/truststore properties and add this property: java.protocol.handler.pkgs, with this value: com.ibm.net.ssl.internal.www.protocol. This property indicates that we are using the IBM HTTPS package for the JSSE framework. Use the JVM custom properties to define your truststore and keystore as described earlier. Since by default the SSL protocol authenticates the server to the client, you may only need a truststore defined. Authenticating the client to the server is optional and is controlled from the server side settings (see Resources). The client application, however, needs to specify its keystore, as we have already described. A client running within the WebSphere Application Server environment may choose to use the WebSphere Application Server file:///C|/developerworks/pdf_0502/0502_benantar/0502_benantar.html (7 of 12) [2/23/2005 6:50:09 PM] IBM WebSphere Developer Technical Journal: Using the Java Secure Socket Extension in WebSphere Application Server server keystore. We do not recommend this, however, because in so doing, a client masquerades under the identity of the application server. If you are concerned about application code illegally accessing the WebSphere Application Server keystore, you can enable Java 2 security. Once enabled, WebSphere Application Server will not allow applications to access the keystore (or in fact any file) without explicitly being granted that permission. Write the code that uses HTTPS The JSSE programming APIs for use with HTTPS are remarkably simple. Essentially, JSSE is used implicitly from code that opens up URLs that happen to point to HTTPS. The following trivial lines demonstrate creating a URL to an HTTPS endpoint and opening an HTTPS connection. Be sure to handle any applicable exceptions properly (refer to the Java networking programming reference). String stringURL = "https://targetHost:9443/MyWebApps/servlet/myServlet"; URL url = new URL(stringURL); HttpsURLConnection urlc =(HttpsURLConnection)url.openConnection(); You can now follow the normal URL programming model for coding the rest of your application. For example, you can now begin reading from this URL connection. These simple lines hide a lot of complexity. When the URL connection is used for the first time, the SSL handshake will automatically occur, authenticating the server to the client by way of the client receiving the server certificate and verifying it against the truststore. By the same token, client authentication may take place if an appropriate keystore is available and the server requests it. All this is done transparently for you by the JSSE runtime. Your exchange with the target server is now protected by the underlying SSL channel. Endpoint validation One important point to make about using SSL in this scenario is that the client is not verifying that the server it is talking to is in fact the intended party. Certificate authentication in this scenario really means "is the server providing a valid certificate?" The JSSE runtime will ensure that, but it doesn't guarantee that the server is the right server. Web browsers work around this issue by checking the server's certificate after validation to see if the Subject name in the certificate is the same as the DNS host name being accessed. For maximum security (if you are concerned about this very subtle -- and difficult to exploit -- security hole), you should perform validation similar to the Web browser, and determine the server's certificate using HttpsURLConnection.getServerCertificates(). Special case: A Web services client If you are interested in accessing a Web services endpoint as a client using HTTPS, you can do something very similar to the previous example. This second example uses a Web services client proxy generated by IBM tooling to open an HTTPS connection. As in the previous example, we assume that the steps indicated earlier in this paper have already been followed. String string URL = "https://targetHost:9443/MyWebApps/services/MyService"; ServiceProxy proxy = new ServiceProxy(); proxy.setEndPoint(stringURL); // proceed to invoke the proxy methods based on your application // ServiceProxy should be replaced by the name of your own application proxy ... file:///C|/developerworks/pdf_0502/0502_benantar/0502_benantar.html (8 of 12) [2/23/2005 6:50:09 PM] IBM WebSphere Developer Technical Journal: Using the Java Secure Socket Extension in WebSphere Application Server Client side JSSE socket programming We have shown you how to open HTTPS connections that implicitly use JSSE. For many situations, that's all you need. Sometimes, though, it is necessary to code directly to the JSSE APIs when you are accessing something that uses SSL, but not HTTPS. Next, we show a little code sample that should show you the basics. As before, we assume you have configured the truststore and keystore environment properties. Essentially, we get an SSL socket factory (default should be okay), create an SSL socket out of it, and begin reading writing to it: SSLSocketFactory sslFactory=(SSLSocketFactory)SSLSocketFactory.getDefault(); SSLSocket s=(SSLSocket)sslFactory.createSocket(targetHost,port); //substitute your targetHost and port // example OutputStream out=s.getOutputStream(); InputStream in=s.getInputStream(); A call to SSLSocket.startHandshake() is not needed unless you want to reset the parameters of the handshake. Can I use multiple keystores/truststores simultaneously? Up to now, we have assumed in our examples that there is one truststore and keystore that is being used throughout the JVM. A client that is interacting with multiple services at the same time may find the need to use multiple keystores or truststores in order to establish SSL connections with each individual target application. The JSSE programming model enables the use of multiple such credential stores by way of maintaining a separate SSL context per individual target interaction. Each such context is encapsulated by a new SSLContext object. The following programming sequence shows how to define multiple keystores/truststore: 1. Load your desired keystore into the runtime: KeyStore ks = KeyStore.getInstance("JKS"); ks.load(new FileInputStream("yourKeyStore"), "yourPassword".toCharArray()); 2. Instantiate and then initialize a KeyManagerFactory object to encapsulate the underlying keystore: KeyManagerFactory kmf = KeyManagerFactory.getInstance("IbmX509"); kmf.init(ks, "yourPassword".toCharArray()); 3. Load your desired truststore into the runtime (instantiated as a KeyStore object): KeyStore ts = KeyStore.getInstance("JKS"); ts.load(new FileInputStream("yourTrustStore"), "yourPassword".toCharArray()); file:///C|/developerworks/pdf_0502/0502_benantar/0502_benantar.html (9 of 12) [2/23/2005 6:50:09 PM] IBM WebSphere Developer Technical Journal: Using the Java Secure Socket Extension in WebSphere Application Server 4. Instantiate a TrustManagerFactory object and initialize it with your truststore: TrustManager[] tm; TrustManagerFactory tmf = TrustManagerFactory.getInstance("IbmX509"); tmf.init(ts); tm = tmf.getTrustManagers(); 5. Get an instance of the SSLContext class: sslContext = SSLContext.getInstance("SSL"); 6. Initialize this instance using the current trust manager (encapsulating the trusted CAs) and the key manager (encapsulating the client's credential): sslContext.init(kmf.getKeyManagers(), tm, null); 7. Use the current SSLContext object to get a SSL Socket Factory and instantiate an SSL socket out of it, as described in the previous section: SSLSocketFactory factory = sslContext.getSocketFactory(); The main point here is the fact that the SSLContext class is not a singleton; that is, each getInstance call returns a different SSLContext object. HTTPS with multiple keystores As we have seen, trust and key management for the HTTPS URL implementation is environment specific. This makes it easy to use SSL by simply configuring or specifying a few JVM properties. However, there is a disadvantage to this approach in that the specified properties will dictate the use of a single truststore/keystore. To overcome this situation, we use the JSSE interfaces to define an SSLContext for each separate HTTPS connection. The following code shows how you set up a custom keystore/trustore for your URL connection: file:///C|/developerworks/pdf_0502/0502_benantar/0502_benantar.html (10 of 12) [2/23/2005 6:50:09 PM] IBM WebSphere Developer Technical Journal: Using the Java Secure Socket Extension in WebSphere Application Server KeyStore ks = KeyStore.getInstance("JKS"); ks.load(new FileInputStream("yourKeyStore"), "yourPassword".toCharArray()); KeyManagerFactory kmf = KeyManagerFactory.getInstance("IbmX509"); kmf.init(ks, " yourPassword ".toCharArray()); TrustManager[] tm; TrustManagerFactory tmf = TrustManagerFactory.getInstance("IbmX509"); tmf.init(ks); tm = tmf.getTrustManagers(); KeyStore ts = KeyStore.getInstance("JKS"); ts.load(new FileInputStream("yourTrustStore"), "yourPassword".toCharArray()); TrustManager[] tm; TrustManagerFactory tmf = TrustManagerFactory.getInstance("IbmX509"); tmf.init(ts); tm = tmf.getTrustManagers(); SSLContext sslContext = SSLContext.getInstance("SSL"); sslContext.init(kmf.getKeyManagers(), tm, null); SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); URL url = new URL(stringURL); urlc = (HttpsURLConnection) url.openConnection(); urlc.setSSLSocketFactory(sslSocketFactory); // at this point communication with this target url // is set to use SSL with your custom truststore and keystore While we won't show it here, if you wish to perform something similar with Web services clients, you will have to specify the keyrings to use via the Web services client deployment descriptors. Conclusion WebSphere Application Server fully supports JSSE as an SPI provider for the framework, and as a set of user APIs. As such, JSSE is readily avaialble for applications that need to establish SSL/TLS connections within the WebSphere Application Server environment. In this article, we have examined and presented recommended ways for using JSSE with an emphasis on how to maintain application portability by avoiding the hardcoding of JSSE implementation-specific constructs. Remember, of course, that the trust foundations for SSL/TLS connections rest foremost on the reliability and security of the public key certificates and their corresponding private keys. We also described how to use custom truststores and keystores in your application, as well as how to use multiple such constructs to establish connections with different entities. Resources q Introduction to the Public Key Infrastructure for the Internet, Messaoud Benantar, Prentice Hall, ISBN 0-13-060927-7, 2001 IBM Secure Socket Layer Introduction and iKeyman q file:///C|/developerworks/pdf_0502/0502_benantar/0502_benantar.html (11 of 12) [2/23/2005 6:50:09 PM] IBM WebSphere Developer Technical Journal: Using the Java Secure Socket Extension in WebSphere Application Server q SSL and TLS, Designing and Building Secure Systems, Eric Rescorla About the authors Messaoud Benantar is a senior software engineer with IBM Software Services for WebSphere. He spent most of his career as a software developer working in IBM Large Systems Division, IBM Software Group/Tivoli, and IBM Global Services. His focus is on middleware and computing security. Keys Botzum is a senior consultant with IBM Software Services for WebSphere. He has over 10 years of experience in large scale distributed system design, and additionally specializes in security. Mr. Botzum has worked with a variety of distributed technologies, including Sun RPC, DCE, CORBA, AFS, and DFS. Recently, he has been focusing on J2EE and related technologies. He holds a Masters degree in Computer Science from Stanford University, and a B.S. in Applied Mathematics/Computer Science from Carnegie Mellon University. Mr. Botzum has published numerous papers on WebSphere and WebSphere security. Additional articles and presentations by Keys Botzum can be found at http://www.keysbotzum.com, as well as on IBM developerWorks WebSphere. He is also an author of IBM WebSphere: Deployment and Advanced Configuration. file:///C|/developerworks/pdf_0502/0502_benantar/0502_benantar.html (12 of 12) [2/23/2005 6:50:09 PM] IBM WebSphere Developer Technical Journal: Accelerated JSF development ...tional Application Developer and WebSphere Application Server -- Part 3 IBM WebSphere Developer Technical Journal: Accelerated JSF development for XML-based SOA using Rational Application Developer and WebSphere Application Server -- Part 3 Manipulating SDO instances Level: Intermediate Narinder Makin (nmakin@us.ibm.com) Advisory Software Engineer, IBM, Rational SOA tools 23 Feb 2005 Contents: Introduction Installing the XSD SDO Transform feature XSD SDO Transform feature contents This is Part 3 in a series that presents a solution that accelerates presentation development of XMLImport project interchange based Service Oriented Architecture (SOA) applications. This solution includes an Eclipse feature that Analyzing the SDOs enables the generation of statically typed Service Data Objects (SDO) for an XSD Schema, and provides a runtime framework for using SDOs in the transformation of presentation element data to Creating an XML request and from XML data. Part 3 highlights common techniques for manipulating SDO instances. SDO API usage Introduction This five-part article series presents a solution that accelerates presentation development of XML-based SOA applications, and includes an Eclipse feature that enables the generation of statically typed service data objects (SDO) for an XSD Schema, and a runtime framework for the transformation of presentation element data to/from XML data using SDOs. In this series: q Aggregate API usage Using the XSD-to-SDO generator Conclusion Resources q q Part 1 walked through the development of a simple JavaServer™ Faces (JSF) application using the supplied plug-in set that communicates to a service per the specified XML schema. The application scenario we used makes one service invocation that sends one XML request and receives one XML response, and illustrates the master-detail view of data objects along with pagination and sorting capabilities. Part 2 enhanced the solution from Part 1 to include create, update, and delete functions, plus customizations to the generated SDOs with local variable addition and basic transformations. We illustrated a scenario of multiple schema models, multiple requests/responses for a single page, and showed the JSF dropdown control binding for XML data. In Part 3, we will provide tips for XML SDO usage in IBM® Rational® Application Developer V6 and for using aggregate methods, such as sum, mean, and others, that are provided with the transformation feature. Download About the author Rate this article Related content: IBM WebSphere Developer Technical Journal Part 1: Introducing the XSD SDO transform feature Part 2: Extending and customizing an SDO solution IBM Rational Application Developer V6 (hereafter referred to as Application Developer) and IBM Websphere® Application Server V6 are required to take advantage of this transformation feature. Installing the XSD SDO Transform feature To install the XSD SDO Transform feature, follow the steps detailed in Part 1. XSD SDO Transform feature contents The XSD SDO Transform feature contains artifacts for generating the SDO package from an XSD schema, and framework components to transform an SDO package instance to/from an XML instance document: 1. Create SDO Package Action This action on the XSD resources generates the SDO package from an XSD schema (Figure 1). Figure 1. Create SDO Package file:///C|/developerworks/pdf_0502/0502_makin/0502_makin.html (1 of 31) [2/23/2005 6:50:17 PM] IBM WebSphere Developer Technical Journal: Accelerated JSF development ...tional Application Developer and WebSphere Application Server -- Part 3 2. dw.ibm.etools.xsd.sdo.xmltransformservice.XMLTransformServiceFactory This class provides the APIs to transform an SDO package instance to/from XML instance document. 3. dw.ibm.etools.xsd.sdo.xmltransforms.util.ObjectUtil This class provides aggregate and helper methods that operate on the SDO objects. Import project interchange Import the project interchange xyzinsurancetestclient_pi.zipdownload file into the Application Developer workspace. As a result, the XYZInsuranceTestClient project is imported (Figure 2). This Java™ project contains a unit test Java class with all the methods described below. The SDO package in included in this Java project for simplicity, and the SDO runtime is present in its classpath. You can choose to reference the Web project that contains the SDO package, or create this Java class within the project that contains the SDO package. The supplied Eclipse Modeling Framework (EMF) JAR file, emf.jar, or the equivalent JAR files from the EMF Web Site (ecore.sdo.jar, commonj.sdo.jar, ecore.xmi.jar, ecore.jar, common.jar), should be added to the project's classpath and the build path. The xsdsdotransform.jar file is also added to the project. Later, we will describe using the SDO generator feature shipped with Application Developer to create the SDO package from an XSD in a standalone Java project. Figure 2. Imported project interchange file:///C|/developerworks/pdf_0502/0502_makin/0502_makin.html (2 of 31) [2/23/2005 6:50:17 PM] IBM WebSphere Developer Technical Journal: Accelerated JSF development ...tional Application Developer and WebSphere Application Server -- Part 3 Analyzing the SDOs In this section, we will analyze the Java client that shows the APIs used to manipulate the generated SDO package. We will also look at other API usage on the XMLTransformServiceFactory, as well as the aggregate methods provided with a utility class, ObjectUtil. As illustrated in the previous articles, the SDO package name for an XSD is determined from the targetNamespace declaration of the schema definition (Figure 3). The generated SDO package contains a DocumentRoot class that acts as a root container for all the types that are defined in the schema (Figure 4). A Java class is generated for every type that is defined in the schema. This generated Java class contains all the elements and attributes (as Java types) that are defined for that XSD type, a list for all multi-valued elements, and a reference for any single valued element. Figure 3. TargetNamespace definition Figure 4. Generated SDO java package file:///C|/developerworks/pdf_0502/0502_makin/0502_makin.html (3 of 31) [2/23/2005 6:50:17 PM] IBM WebSphere Developer Technical Journal: Accelerated JSF development ...tional Application Developer and WebSphere Application Server -- Part 3 The classes that are generated for the XSD schema types are initialized in the package registry, such that the XSD types to and from the Java types can can be resolved when transformation takes place. In the case of a large schema that generates a large number of classes, the initialization code is performed by loading an EMF resource. In case of smaller schema (determined based on the computation of total number of classes, attributes, and so on), the initialization code is generated within the Package class itself. The create methods are also generated for all the XSD reference types in the Java class. These APIs can be used to create an instance of any of the generated SDO Java types. As shown in Listing 1, an instance of brokerType is created and added to the list contained in the instance of the BrokerServiceType SDO. Listing 1 public void TestCreateReference(){ DocumentRoot root = DocumentRoot)XMLTransformServiceFactory.INSTANCE.create (BrokerservicePackage.eINSTANCE.getNsURI()); root.getXMLNSPrefixMap().put("", BrokerservicePackage.eINSTANCE.getNsURI()); xyz.brokerservice.BrokerServiceType bs = root.createBrokerService(); BrokerType bType = bs.createBroker(); bType.setBrokerId("111"); bType.setFirstName("Joe"); System.out.println(XMLTransformServiceFactory.INSTANCE.convert((DataObject)root)); } The generated package class contains a method for creating or accessing the Java types for all the types and attributes (Listing 2). Listing 2 file:///C|/developerworks/pdf_0502/0502_makin/0502_makin.html (4 of 31) [2/23/2005 6:50:17 PM] IBM WebSphere Developer Technical Journal: Accelerated JSF development ...tional Application Developer and WebSphere Application Server -- Part 3 public void TestTypeCreation(){ EClass brokerType = BrokerservicePackage.eINSTANCE.getBrokerType(); System.out.println("Type Name: " + brokerType.getName()); } The generated factory class provides APIs for creating instances of any generated SDO Java type. As seen in Listing 3, to create an instance of the brokerType, you can use the createBrokerType API. This newly created instance is not added to any list or any reference, as is the related API shown in Listing 1. The setBroker API is used to set the newly created instance in the brokerServiceType. Based on the requirement, you may use either instance creation APIs described here. Listing 3 public void TestInstanceCreation(){ DocumentRoot root = DocumentRoot)XMLTransformServiceFactory.INSTANCE.create (BrokerservicePackage.eINSTANCE.getNsURI()); root.getXMLNSPrefixMap().put("", BrokerservicePackage.eINSTANCE.getNsURI()); xyz.brokerservice.BrokerServiceType bs = root.createBrokerService(); BrokerType bType = BrokerserviceFactory.eINSTANCE.createBrokerType(); bs.setBroker(bType); bType.setBrokerId("111"); bType.setFirstName("Joe"); System.out.println(XMLTransformServiceFactory.INSTANCE.convert((DataObject)root)); } For a detailed overview of the EMF framework, see Eclipse Modeling Framework Overview. Creating an XML request In the previous articles, we saw how the XMLTransformFactory load and convert APIs were used to serialize a graph of SDO objects to and from an XML stream. There are also situations when you would need to create a new instance of an SDO object (or a graph of SDO objects), and serialize that into XML. The create API in XMLTransformFactory can be used for this, as shown in Listing 4a. The output of the method is shown in Listing 4b. Listing 4a. Method public void TestNewDocumentCreation(){ DocumentRoot root = DocumentRoot)XMLTransformServiceFactory.INSTANCE.create (BrokerservicePackage.eINSTANCE.getNsURI()); xyz.brokerservice.BrokerServiceType bs = root.createBrokerService(); BrokerType bType = bs.createBroker(); bType.setBrokerId("111"); bType.setFirstName("Joe"); System.out.println(XMLTransformServiceFactory.INSTANCE.convert((DataObject)root)); } Listing 4b. Output file:///C|/developerworks/pdf_0502/0502_makin/0502_makin.html (5 of 31) [2/23/2005 6:50:17 PM] IBM WebSphere Developer Technical Journal: Accelerated JSF development ...tional Application Developer and WebSphere Application Server -- Part 3 Joe Changing the namespace for the serialized XML The serialized XML in the above example contains the fully qualified elements with a new namespace declaration. If the back end system that consumes this generated XML is not capable of handling such elements, the serializer can be configured to generate a default namespace declaration. Though not recommended, this can be desirable for specific situations. The method (Listing 5a) and output (Listing 5b) are shown below. Listing 5a. Method public void TestNamespaceRemove(){ DocumentRoot root = DocumentRoot)XMLTransformServiceFactory.INSTANCE.create (BrokerservicePackage.eINSTANCE.getNsURI()); root.getXMLNSPrefixMap().put("", BrokerservicePackage.eINSTANCE.getNsURI()); xyz.brokerservice.BrokerServiceType bs = root.createBrokerService(); BrokerType bType = bs.createBroker(); bType.setBrokerId("111"); bType.setFirstName("Joe"); System.out.println(XMLTransformServiceFactory.INSTANCE.convert((DataObject)root)); } Listing 5b. Output Joe Handling schema changes Let's consider a scenario where the service generating the XML response is upgraded to comply to a new schema definition (BrokerServiceV2.xsd, included in the xsd_sdo_soa_part3_listings.zipdownload file), and that schema definition contains more elements or attributes than the one used for generating the SDO package. The serializer used by the XMLTransformServiceFactory is preconfigured to record any new elements and attributes that were not part of original schema. The "Version 2" XML response (BrokerDetailResponseV2.xml, included in the xsd_sdo_soa_part3_listings.zipdownload file) can be loaded in to an SDO package generated with a "Version 1" schema. If the package is serialized to XML, it will contain the optional elements that were recorded on load, as shown in Figure 5. Figure 5. BrokerServiceV1.xsd file:///C|/developerworks/pdf_0502/0502_makin/0502_makin.html (6 of 31) [2/23/2005 6:50:17 PM] IBM WebSphere Developer Technical Journal: Accelerated JSF development ...tional Application Developer and WebSphere Application Server -- Part 3 Listing 6. BrokerDetailResponseV1.xml Narinder Makin Dan Moore 1967-08-13 113 Oak Pine St. Santa Clara LA 91929 US file:///C|/developerworks/pdf_0502/0502_makin/0502_makin.html (7 of 31) [2/23/2005 6:50:17 PM] IBM WebSphere Developer Technical Journal: Accelerated JSF development ...tional Application Developer and WebSphere Application Server -- Part 3 123 Demi Lane Cary NC 22999 US Life 2004-01-01 2005-01-01 100000.00 Life Insurance policy includes any accidental damages. House 2004-01-01 2005-01-01 50000.00 Home Insurance Car 1 2004-01-01 2005-01-01 15000.00 Car Insurance - Ferrari 2004 - Primary Car Car 2 2004-01-01 2005-01-01 5000.00 Car Insurance - Lexus 2003 - Secondary Car Restaurant 2004-01-01 2005-01-01 25000.00 Business Insurance Restaurant Tom Cross 1970-11-11 113 Duke St. Shelton CT 08989 US file:///C|/developerworks/pdf_0502/0502_makin/0502_makin.html (8 of 31) [2/23/2005 6:50:17 PM] IBM WebSphere Developer Technical Journal: Accelerated JSF development ...tional Application Developer and WebSphere Application Server -- Part 3 123 Lex Lane Fairfield NY 09833 US House 2004-01-01 2005-01-01 2000.00 Home Insurance Life 2004-01-01 2005-01-01 100000.00 Life Insurance Car 1 2004-01-01 2005-01-01 2000.00 Car Insurance - Camry 2004 - Primary Car Continuing with our scenario, to serve the secured service requests for another client, a new optional attribute, securityToken, and a new optional element, ssn, are added to the clientType definition in "Version 2" of brokerservice. A requirement dictates that no modifications should be required in existing client applications for which the SDO packages were generated using the older XSDs. The XMLTransformFactory is configured so that any unknown elements present in the XML stream will be recorded in the SDO instances. When these instances are serialized, these unknown recorded elements (ssn and securityToken) will be serialized as well. Figure 6. BrokerServiceV2.xsd Modifications file:///C|/developerworks/pdf_0502/0502_makin/0502_makin.html (9 of 31) [2/23/2005 6:50:17 PM] IBM WebSphere Developer Technical Journal: Accelerated JSF development ...tional Application Developer and WebSphere Application Server -- Part 3 Listing 7. BrokerDetailResponseV2.xml Narinder Makin Dan Moore 1967-08-13 113 Oak Pine St. Santa Clara LA 91929 US 123 Demi Lane Cary NC 22999 US Life 2004-01-01 2005-01-01 100000.00 Life Insurance policy includes any accidental damages. House 2004-01-01 file:///C|/developerworks/pdf_0502/0502_makin/0502_makin.html (10 of 31) [2/23/2005 6:50:17 PM] IBM WebSphere Developer Technical Journal: Accelerated JSF development ...tional Application Developer and WebSphere Application Server -- Part 3 2005-01-01 50000.00 Home Insurance Car 1 2004-01-01 2005-01-01 15000.00 Car Insurance - Ferrari 2004 - Primary Car Car 2 2004-01-01 2005-01-01 5000.00 Car Insurance - Lexus 2003 - Secondary Car Restaurant 2004-01-01 2005-01-01 25000.00 Business Insurance Restaurant 1234567 Tom Cross 1970-11-11 113 Duke St. Shelton CT 08989 US 123 Lex Lane Fairfield NY 09833 US House 2004-01-01 2005-01-01 2000.00 Home Insurance Life 2004-01-01 file:///C|/developerworks/pdf_0502/0502_makin/0502_makin.html (11 of 31) [2/23/2005 6:50:18 PM] IBM WebSphere Developer Technical Journal: Accelerated JSF development ...tional Application Developer and WebSphere Application Server -- Part 3 2005-01-01 100000.00 Life Insurance Car 1 2004-01-01 2005-01-01 2000.00 Car Insurance - Camry 2004 - Primary Car 12345678 In the code in Listing 8, BrokerDetailResponseV2.xml is loaded and firstName is modified. The dataobject is then serialized back to XML. The serialized XML (Listing 9) contains the modification, along with the optional elements ssn and securityToken that were recorded during the load. Listing 8 public void TestSchemaChange() { xyz.brokerservice.DocumentRoot loaded = ( xyz.brokerservice.DocumentRoot) XMLTransformServiceFactory.INSTANCE.loadFile("./input/brokerDetailResponseV2.xml"); xyz.brokerservice.BrokerServiceType bs = loaded.getBrokerService(); bs.getBroker().setFirstName("NEW NAME"); System.out.println(XMLTransformServiceFactory.INSTANCE.convert((DataObject)loaded)) } Listing 9 NEW NAME Makin Dan Moore 1967-08-13 113 Oak Pine St. Santa Clara LA 91929 US 123 Demi Lane file:///C|/developerworks/pdf_0502/0502_makin/0502_makin.html (12 of 31) [2/23/2005 6:50:18 PM] IBM WebSphere Developer Technical Journal: Accelerated JSF development ...tional Application Developer and WebSphere Application Server -- Part 3 Cary NC 22999 US Life 2004-01-01 2005-01-01 100000.00 Life Insurance policy includes any accidental damages. House 2004-01-01 2005-01-01 50000.00 Home Insurance Car 1 2004-01-01 2005-01-01 15000.00 Car Insurance - Ferrari 2004 - Primary Car Car 2 2004-01-01 2005-01-01 5000.00 Car Insurance - Lexus 2003 - Secondary Car Restaurant 2004-01-01 2005-01-01 25000.00 Business Insurance - Restaurant 1234567 Tom Cross 1970-11-11 113 Duke St. Shelton CT 08989 US 123 Lex Lane file:///C|/developerworks/pdf_0502/0502_makin/0502_makin.html (13 of 31) [2/23/2005 6:50:18 PM] IBM WebSphere Developer Technical Journal: Accelerated JSF development ...tional Application Developer and WebSphere Application Server -- Part 3 Fairfield NY 09833 US House 2004-01-01 2005-01-01 2000.00 Home Insurance Life 2004-01-01 2005-01-01 100000.00 Life Insurance Car 1 2004-01-01 2005-01-01 2000.00 Car Insurance - Camry 2004 - Primary Car 12345678 The above behavior may not be required, and so can be turned off by modifying the serializer options shown in Listing 10a, which uses the getOptions API. The serializer throws an exception for the elements that are in the XML being loaded but were not part of the original schema used to generate the package. The XML output is shown in Listing 10b. Listing 10a. Method public void TestRestrictSchemaChange() { try { XMLTransformServiceFactory.INSTANCE.getOptions().put (org.eclipse.emf.ecore.xmi.XMLResource.OPTION_RECORD_UNKNOWN_FEATURE, Boolean.FALSE); xyz.brokerservice.DocumentRoot loaded = ( xyz.brokerservice.DocumentRoot) XMLTransformServiceFactory.INSTANCE.loadFile("./DataFile/brokerDetailResponseV2.xml"); xyz.brokerservice.BrokerServiceType bs = loaded.getBrokerService(); bs.getBroker().setFirstName("NEW NAME"); System.out.println(XMLTransformServiceFactory.INSTANCE.convert((DataObject)loaded)); } catch(Exception e) { file:///C|/developerworks/pdf_0502/0502_makin/0502_makin.html (14 of 31) [2/23/2005 6:50:18 PM] IBM WebSphere Developer Technical Journal: Accelerated JSF development ...tional Application Developer and WebSphere Application Server -- Part 3 e.printStackTrace(); } } Listing 10b. Output org.eclipse.emf.ecore.xmi.FeatureNotFoundException: Feature 'securityToken' not found. (root.xml, 6, 56) at org.eclipse.emf.ecore.xmi.impl.XMLHandler.reportUnknownFeature(XMLHandler.java:1168) at org.eclipse.emf.ecore.xmi.impl.XMLHandler.handleUnknownFeature(XMLHandler.java:1138) at org.eclipse.emf.ecore.xmi.impl.XMLHandler.setAttribValue(XMLHandler.java:1780) at org.eclipse.emf.ecore.xmi.impl.SAXXMLHandler.handleObjectAttribs(SAXXMLHandler.java:145) at org.eclipse.emf.ecore.xmi.impl.XMLHandler.createObjectFromFactory(XMLHandler.java:1346) at org.eclipse.emf.ecore.xmi.impl.XMLHandler.createObjectFromFeatureType(XMLHandler.java:1318) at org.eclipse.emf.ecore.xmi.impl.XMLHandler.createObject(XMLHandler.java:1213) at org.eclipse.emf.ecore.xmi.impl.XMLHandler.handleFeature(XMLHandler.java:1022) at org.eclipse.emf.ecore.xmi.impl.XMLHandler.processElement(XMLHandler.java:448) at org.eclipse.emf.ecore.xmi.impl.XMLHandler.startElement(XMLHandler.java:431) at org.eclipse.emf.ecore.xmi.impl.SAXWrapper.startElement(SAXWrapper.java:75) at org.apache.xerces.parsers.AbstractSAXParser.startElement(Unknown Source) at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanStartElement(Unknown Source) at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl $FragmentContentDispatcher.dispatch(Unknown Source) at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source) at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source) at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source) at org.apache.xerces.parsers.XMLParser.parse(Unknown Source) at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source) at javax.xml.parsers.SAXParser.parse(Unknown Source) at org.eclipse.emf.ecore.xmi.impl.XMLLoadImpl.load(XMLLoadImpl.java:129) at org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl.doLoad(XMLResourceImpl.java:155) at org.eclipse.emf.ecore.resource.impl.ResourceImpl.load(ResourceImpl.java:884) at dw.ibm.etools.xsd.sdo.xmltransformservice.impl.XMLTransformServiceImpl.load (XMLTransformServiceImpl.java:85) at dw.ibm.etools.xsd.sdo.xmltransformservice.impl.XMLTransformServiceImpl.load (XMLTransformServiceImpl.java:102) at dw.ibm.etools.xsd.sdo.xmltransformservice.impl.XMLTransformServiceFactoryImpl.loadStream (XMLTransformServiceFactoryImpl.java:50) file:///C|/developerworks/pdf_0502/0502_makin/0502_makin.html (15 of 31) [2/23/2005 6:50:18 PM] IBM WebSphere Developer Technical Journal: Accelerated JSF development ...tional Application Developer and WebSphere Application Server -- Part 3 at dw.ibm.etools.xsd.sdo.xmltransformservice.impl.XMLTransformServiceFactoryImpl.loadFile (XMLTransformServiceFactoryImpl.java:65) at sdotestclient.TestClient.TestRestrictSchemaChange(TestClient.java:101) at sdotestclient.TestClient.main(TestClient.java:33) java.lang.NullPointerException at sdotestclient.TestClient.TestRestrictSchemaChange(TestClient.java:102) at sdotestclient.TestClient.main(TestClient.java:33) SDO API usage The generated SDO package uses an underlying Eclipse Modeling Framework implementation. The EMF provides a generic navigation model for the graph or related (or unrelated) objects, and contains a built-in change notification mechanism. Thus, the generated SDO packages have APIs that enable traversing the related (or unrelated) SDOs. Any modifications to any of these object instances or their lists result in notification issues to manage the changes, as per the containment of these objects. The next sections highlight basic considerations when manipulating SDO instances loaded from an XML stream. The functions covered are: q q q q Add Copy Delete Traverse. (See Resources for more information on EMF and SDOs.) Add As we saw in the previous section, a new instance of an SDO can be created either by using the factory class generated in the util package, or by using the create for the related SDO. Let's consider an example where we have an instance of an SDO graph loaded from an XML request. We now need to create a new SDO graph that contains the instances from the loaded SDO graph. In Listing 11a, the broker instance from moveFrom is set in the moveTo SDO. If we check the contents of moveFrom, we will see that it no longer contains the broker instance, while the moveTo SDO does. A simple, add operation in this case, by default, results in a move from the original container to the new container. An SDO instance thus can only be contained by one container at a time. Listing 11a. Method public void TestMove() { xyz.brokerservice.DocumentRoot moveFrom = ( xyz.brokerservice.DocumentRoot) XMLTransformServiceFactory.INSTANCE.loadFile("./DataFile/brokerDetailResponseV1.xml"); xyz.brokerservice.DocumentRoot moveTo = xyz.brokerservice.DocumentRoot) XMLTransformServiceFactory.INSTANCE.create(BrokerservicePackage.eINSTANCE.getNsURI()); moveTo.getXMLNSPrefixMap().put("", BrokerservicePackage.eINSTANCE.getNsURI()); moveTo.createBrokerService().setBroker(moveFrom.getBrokerService().getBroker()); System.out.println("**********Changes in Original XML********"); System.out.println(XMLTransformServiceFactory.INSTANCE.convert((DataObject)moveFrom)); System.out.println("**********************************************************"); System.out.println("**********Target XML**************************"); System.out.println(XMLTransformServiceFactory.INSTANCE.convert((DataObject)moveTo)); file:///C|/developerworks/pdf_0502/0502_makin/0502_makin.html (16 of 31) [2/23/2005 6:50:18 PM] IBM WebSphere Developer Technical Journal: Accelerated JSF development ...tional Application Developer and WebSphere Application Server -- Part 3 System.out.println("**********************************************************"); } Listing 11b. Output **********Changes in Original XML******** ********************************************************** **********Target XML************************** Narinder Makin Dan Moore 1967-08-13 113 Oak Pine St. Santa Clara LA 91929 US 123 Demi Lane Cary NC 22999 US Life 2004-01-01 2005-01-01 100000.00 Life Insurance policy includes any accidental damages. House 2004-01-01 2005-01-01 50000.00 Home Insurance Car 1 2004-01-01 2005-01-01 15000.00 Car Insurance - Ferrari 2004 - Primary Car file:///C|/developerworks/pdf_0502/0502_makin/0502_makin.html (17 of 31) [2/23/2005 6:50:18 PM] IBM WebSphere Developer Technical Journal: Accelerated JSF development ...tional Application Developer and WebSphere Application Server -- Part 3 Car 2 2004-01-01 2005-01-01 5000.00 Car Insurance - Lexus 2003 - Secondary Car Restaurant 2004-01-01 2005-01-01 25000.00 Business Insurance - Restaurant Tom Cross 1970-11-11 113 Duke St. Shelton CT 08989 US 123 Lex Lane Fairfield NY 09833 US House 2004-01-01 2005-01-01 2000.00 Home Insurance Life 2004-01-01 2005-01-01 100000.00 Life Insurance Car 1 2004-01-01 2005-01-01 2000.00 Car Insurance - Camry 2004 - Primary Car file:///C|/developerworks/pdf_0502/0502_makin/0502_makin.html (18 of 31) [2/23/2005 6:50:18 PM] IBM WebSphere Developer Technical Journal: Accelerated JSF development ...tional Application Developer and WebSphere Application Server -- Part 3 ********************************************************** Copy If a true copy operation is required, such that both the SDO graphs will contain the SDOs, an ObjectUtil.copyFrom operation should be used instead, since an EMF API is used internally. This API performs a deep copy, which includes all the nested children of the object being copied into the new graph. In Listing 12a, the contents of copyFrom are not altered from before, but copyTo contains a new instance of the broker with exactly the same structured data as was retrieved for it from the copyFrom SDO. Listing 12a. Method public void TestCopy() { xyz.brokerservice.DocumentRoot copyFrom = (xyz.brokerservice.DocumentRoot) XMLTransformServiceFactory.INSTANCE.loadFile("./DataFile/brokerDetailResponseV1.xml"); xyz.brokerservice.DocumentRoot copyTo = (xyz.brokerservice.DocumentRoot) XMLTransformServiceFactory.INSTANCE.create(BrokerservicePackage.eINSTANCE.getNsURI()); copyTo.getXMLNSPrefixMap().put("", BrokerservicePackage.eINSTANCE.getNsURI()); copyTo.createBrokerService().setBroker((BrokerType)ObjectUtil.INSTANCE.copyFrom((DataObject) copyFrom.getBrokerService().getBroker())); System.out.println("**********No Changes in Original XML********"); System.out.println(XMLTransformServiceFactory.INSTANCE.convert((DataObject)copyFrom)); System.out.println("**********************************************************"); System.out.println("**********Target XML**************************"); System.out.println(XMLTransformServiceFactory.INSTANCE.convert((DataObject)copyTo)); System.out.println("**********************************************************"); } Listing 12b. Output **********No Changes in Original XML******** Narinder Makin Dan Moore 1967-08-13 113 Oak Pine St. Santa Clara LA file:///C|/developerworks/pdf_0502/0502_makin/0502_makin.html (19 of 31) [2/23/2005 6:50:18 PM] IBM WebSphere Developer Technical Journal: Accelerated JSF development ...tional Application Developer and WebSphere Application Server -- Part 3 91929 US 123 Demi Lane Cary NC 22999 US Life 2004-01-01 2005-01-01 100000.00 Life Insurance policy includes any accidental damages. House 2004-01-01 2005-01-01 50000.00 Home Insurance Car 1 2004-01-01 2005-01-01 15000.00 Car Insurance - Ferrari 2004 - Primary Car Car 2 2004-01-01 2005-01-01 5000.00 Car Insurance - Lexus 2003 - Secondary Car Restaurant 2004-01-01 2005-01-01 25000.00 Business Insurance - Restaurant Tom Cross 1970-11-11 113 Duke St. Shelton CT 08989 file:///C|/developerworks/pdf_0502/0502_makin/0502_makin.html (20 of 31) [2/23/2005 6:50:18 PM] IBM WebSphere Developer Technical Journal: Accelerated JSF development ...tional Application Developer and WebSphere Application Server -- Part 3 US 123 Lex Lane Fairfield NY 09833 US House 2004-01-01 2005-01-01 2000.00 Home Insurance Life 2004-01-01 2005-01-01 100000.00 Life Insurance Car 1 2004-01-01 2005-01-01 2000.00 Car Insurance - Camry 2004 - Primary Car ********************************************************** **********Target XML************************** Narinder Makin Dan Moore 1967-08-13 113 Oak Pine St. Santa Clara LA 91929 US 123 Demi Lane Cary NC 22999 US file:///C|/developerworks/pdf_0502/0502_makin/0502_makin.html (21 of 31) [2/23/2005 6:50:18 PM] IBM WebSphere Developer Technical Journal: Accelerated JSF development ...tional Application Developer and WebSphere Application Server -- Part 3 Life 2004-01-01 2005-01-01 100000.00 Life Insurance policy includes any accidental damages. House 2004-01-01 2005-01-01 50000.00 Home Insurance Car 1 2004-01-01 2005-01-01 15000.00 Car Insurance - Ferrari 2004 - Primary Car Car 2 2004-01-01 2005-01-01 5000.00 Car Insurance - Lexus 2003 - Secondary Car Restaurant 2004-01-01 2005-01-01 25000.00 Business Insurance - Restaurant Tom Cross 1970-11-11 113 Duke St. Shelton CT 08989 US 123 Lex Lane Fairfield NY 09833 US file:///C|/developerworks/pdf_0502/0502_makin/0502_makin.html (22 of 31) [2/23/2005 6:50:18 PM] IBM WebSphere Developer Technical Journal: Accelerated JSF development ...tional Application Developer and WebSphere Application Server -- Part 3 House 2004-01-01 2005-01-01 2000.00 Home Insurance Life 2004-01-01 2005-01-01 100000.00 Life Insurance Car 1 2004-01-01 2005-01-01 2000.00 Car Insurance - Camry 2004 - Primary Car ********************************************************** Delete The SDO can be deleted from the container as a simple list "remove" operation.. As shown in Listing 13a, the instance of the client is removed from the broker instance. Listing 13a. Method public void TestDelete() { xyz.brokerservice.DocumentRoot deleteFrom = ( xyz.brokerservice.DocumentRoot) XMLTransformServiceFactory.INSTANCE.loadFile("./DataFile/brokerDetailResponseV1.xml"); BrokerType brokerType = deleteFrom.getBrokerService().getBroker(); List clientList = brokerType.getClient(); Iterator clientListItr = clientList.iterator(); ClientType clientMoore = null; while(clientListItr.hasNext()){ ClientType clientType = (ClientType)clientListItr.next(); if(clientType.getLastName().equals("Moore")){ clientMoore = clientType; break; } } clientList.remove(clientMoore); System.out.println("**********Client with last name 'Moore' removed from Original XML********"); System.out.println(XMLTransformServiceFactory.INSTANCE.convert((DataObject)deleteFrom)); System.out.println("**********************************************************"); file:///C|/developerworks/pdf_0502/0502_makin/0502_makin.html (23 of 31) [2/23/2005 6:50:18 PM] IBM WebSphere Developer Technical Journal: Accelerated JSF development ...tional Application Developer and WebSphere Application Server -- Part 3 } Listing 13b. Output **********Client with last name 'Moore' removed from Original XML******** Narinder Makin Tom Cross 1970-11-11 113 Duke St. Shelton CT 08989 US 123 Lex Lane Fairfield NY 09833 US House 2004-01-01 2005-01-01 2000.00 Home Insurance Life 2004-01-01 2005-01-01 100000.00 Life Insurance Car 1 2004-01-01 2005-01-01 2000.00 Car Insurance - Camry 2004 - Primary Car ********************************************************** file:///C|/developerworks/pdf_0502/0502_makin/0502_makin.html (24 of 31) [2/23/2005 6:50:18 PM] IBM WebSphere Developer Technical Journal: Accelerated JSF development ...tional Application Developer and WebSphere Application Server -- Part 3 Traverse Since the SDO implementation is EMF based, the EMF traversal APIs can be used in order to traverse an SDO graph. You can either access the related children, or you can traverse the parent object tree using the getParent API in ObjectUtil. This API traverses the reference to the container SDO that contains the SDO as a typed reference or in a list. In Listings 14a and 14b, the broker instance is traversed from an instance of client SDO. Listing 14a. Code public void TestGraphTravesal() { xyz.brokerservice.DocumentRoot traverseFrom = ( xyz.brokerservice.DocumentRoot) XMLTransformServiceFactory.INSTANCE.loadFile("./DataFile/brokerDetailResponseV1.xml"); BrokerType brokerType = traverseFrom.getBrokerService().getBroker(); System.out.println("BrokerType is: " + brokerType.getFirstName()); List clientList = brokerType.getClient(); Iterator clientListItr = clientList.iterator(); ClientType clientMoore = null; while(clientListItr.hasNext()){ ClientType clientType = (ClientType)clientListItr.next(); BrokerType parent = (BrokerType)ObjectUtil.INSTANCE.getParent(((DataObject)clientType)); System.out.println("Parent brokerType is: " + parent.getFirstName()); } } Listing 14b. Results BrokerType is: Narinder Parent brokerType is: Narinder Parent brokerType is: Narinder Aggregate API usage Utility APIs, such as sort, sum, mean, and so on, are commonly used within and throughout applications. An application created for an XML-based SOA may typically require coding of such APIs. Since we are using an SDO implementation, these methods can be provided generically across the SDO instances. The ObjectUtil helper class, provided with the XSD SDO Transform feature, contains aggregate and other utility APIs that operate generically on the SDO objects. This section illustrates the usage of these APIs: q q q q Sum Mean Min Max. Sum The Sum API can be used to provide a summation of the values of an EAttribute present with in a list. This API is used with a simple call that takes in the list containing the instances and the EAttribute for the attribute. EPackage provides the access to all the EMF types for the EObject and EAttributes present in the SDO package. Attributes of type Integer, Float, Long, Short, Double, BigDecimal, and String are valid for Sum. For an attribute of type String, an attempt is made to implicitly convert it into Long, Double, or Float. Listing 15. Sum API file:///C|/developerworks/pdf_0502/0502_makin/0502_makin.html (25 of 31) [2/23/2005 6:50:18 PM] IBM WebSphere Developer Technical Journal: Accelerated JSF development ...tional Application Developer and WebSphere Application Server -- Part 3 /** * Get the sum for the values of the attribute in an EList * @exception Exception Throws java.lang.Exception * @param list a EList containing the attribute values * @param attr The EAttribute for the attribute whose sum is to be determined * @return Object The sum of the value of the EAttributes in the list.If the length is less than 0 * then return null. If the attribute is not valid for doing sum and mean then return null */ public Object sum(List list, EAttribute attr) throws Exception Mean The Mean API can be used to provide the mean of the EAttribute values present within a list. This API is also used with a simple call that takes in the list containing the instances and the EAttribute for the attribute. Valid attribute types are the same as for Sum. Listing 16. Mean API /** * Get the mean for the values of the attribute in an EList * @exception Exception Throws java.lang.Exception * @param list a EList containing the attribute values * @param attr The EAttribute for the attribute whose mean is to be determined * @return Object The mean of the value of the EAttributes in the list.If the length is less than 0 * then return null. If the attribute is not valid for doing sum and mean then return null */ public Object mean(List list, EAttribute attr) throws Exception Min The Min API can be used to provide the minimum of the values of an EAttribute present within a list. This API is also used with a simple call that takes in the list containing the instances and the EAttribute for the attribute. An attribute of type Integer, Float, Long, Short, Double, BigDecimal, Date, Time, Timestamp, and String are considered valid for Min. Listing 17. Min API /** * Get the minimum value from the attributes in the EList * @param list a EList containing the attribute values * @param attr an EAttribute defining the EType of the attributes in the list * @return Object The minimum value in the list * If the length is less than 0 then return null. * If the attribute is not valid then return null */ public Object min(List list, EAttribute attr) throws Exception Max The Max API can be used to provide the maximum of the values of an EAttribute present with in a list. This API is also used as a simple call that takes in the list containing the instances and the EAttribute for the attribute. Valid attribute types are the same as for Min. file:///C|/developerworks/pdf_0502/0502_makin/0502_makin.html (26 of 31) [2/23/2005 6:50:18 PM] IBM WebSphere Developer Technical Journal: Accelerated JSF development ...tional Application Developer and WebSphere Application Server -- Part 3 Listing 18. Max API /** * Get the maximum value from the attributes in the EList * @param list a EList containing the attribute values * @param attr an EAttribute defining the EType of the attributes in the list * @return Object The maximum value in the list * If the length is less than 0 then return null. * If the attribute is not valid then return null */ public Object max(List list, EAttribute attr) throws Exception The coding and results of each of these aggregate APIs are shown in Figures 19a and 19b. Listing 19a. Code public void TestAggregateAPI(){ xyz.brokerservice.DocumentRoot root = ( xyz.brokerservice.DocumentRoot) XMLTransformServiceFactory.INSTANCE.loadFile("./DataFile/brokerDetailResponseV1.xml"); BrokerServiceType bs = root.getBrokerService(); try { //sum test System.out.println("Sum is : " + ObjectUtil.INSTANCE.sum(bs.getBroker() .getClientAsArray()[0].getPolicy(), BrokerservicePackage.eINSTANCE.getPolicyType_PolicyAmount())); //mean test System.out.println("Mean is : " + ObjectUtil.INSTANCE.mean(bs.getBroker() .getClientAsArray()[0].getPolicy(), BrokerservicePackage.eINSTANCE.getPolicyType_PolicyAmount())); //max test System.out.println("Max is : " + ObjectUtil.INSTANCE.max(bs.getBroker() .getClientAsArray()[0].getPolicy(), BrokerservicePackage.eINSTANCE.getPolicyType_PolicyName())); //min test System.out.println("Min is : " + ObjectUtil.INSTANCE.min(bs.getBroker() .getClientAsArray()[0].getPolicy(), BrokerservicePackage.eINSTANCE.getPolicyType_PolicyName())); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } file:///C|/developerworks/pdf_0502/0502_makin/0502_makin.html (27 of 31) [2/23/2005 6:50:18 PM] IBM WebSphere Developer Technical Journal: Accelerated JSF development ...tional Application Developer and WebSphere Application Server -- Part 3 Listing 19b. Results Sum is : 195000.0 Mean is : 39000.0 Max is : Restaurant Min is : Car 1 Using the XSD-to-SDO generator Application Developer also ships with a feature for generating the SDO package from an XSD document. You can use this feature to generate the SDO Java package rather than use the Create SDO Package action. The code generated with the Create SDO Package action contains the typed array methods, along with the list methods for the related SDO objects. This eases the binding of the datatable to the collection without the prompt for defining the type contained in the collection. Along with that, the generator also adds the required framework JARs to the project so that no manual setup is required. It is viable to use the Create SDO Package action when you require more than just the creation of the SDO package, like when developing a Web project. When a simple Java project is being used, though, you may wish to use the XSD SDO generator and manually add the framework JAR file, xsdsdotransform.jar, to the classpath, and build path of the project if transform capability is required. The EMF framework JARs are automatically added to the project by the generator. (These JARs are also available for download at the EMF Web site, and are equivalent to the emf.jar that is shipped with the Application Developer or WebSphere Application Server runtime.) To use the SDO generator option in Application Developer: 1. Turn on the XML development capability in the Preferences dialog (Figure 7). Figure 7. Turn on XML capability 2. This enables a context menu action for generating Java when an XSD document is selected (Figure 8). Figure 8. Menu action file:///C|/developerworks/pdf_0502/0502_makin/0502_makin.html (28 of 31) [2/23/2005 6:50:18 PM] IBM WebSphere Developer Technical Journal: Accelerated JSF development ...tional Application Developer and WebSphere Application Server -- Part 3 3. In the Generate Java dialog, select SDO Generator to enable generation of the XSD SDO Java package (Figure 9). Figure 9. XSD SDO generator wizard file:///C|/developerworks/pdf_0502/0502_makin/0502_makin.html (29 of 31) [2/23/2005 6:50:18 PM] IBM WebSphere Developer Technical Journal: Accelerated JSF development ...tional Application Developer and WebSphere Application Server -- Part 3 4. As a result of the wizard operation, the SDO Java package is created (Figure 10) and the required framework JARs are added to the build and classpath of the Java project. Figure 10. SDO Java Package Known limitation: XSD inheritance is not supported in the generation of the SDO package. Before creating the SDO package, you will need to fix the generated code manually or merge the schema into a single file. Conclusion Part 3 of this article series highlighted different techniques that are commonly used for manipulating SDO instances when building an XMLbased SOA application. How to use the SDO generator, and the differences in the code generated using the Create SDO package action, were also discussed. Part 4 will focus on portlet development for the XML-based SOA that uses the XSD SDO transform feature, addressing JSR 168 portlet creation, parameter passing across portlets, and setting the target portlet view dynamically on a portlet action in any other portlet. Part 5 will discuss localizing JSF and portlet applications for the XML-based SOA that uses the XSDO SDO transform feature, and will address the localizing static and dynamic content that is displayed based on the preferred locale. Resources q IBM developerWorks Rational file:///C|/developerworks/pdf_0502/0502_makin/0502_makin.html (30 of 31) [2/23/2005 6:50:18 PM] IBM WebSphere Developer Technical Journal: Accelerated JSF development ...tional Application Developer and WebSphere Application Server -- Part 3 q The article Getting started with the Eclipse Platform (developerWorks, November 2002) provides a history and overview of Eclipse, including details on how to install Eclipse and plug-ins. Eclipse In Action: A Guide for Java Developers (Independent Pub Group, 2003) is a must-read for Java developers using Eclipse. An Introduction to Service Data Objects Introduction to Service Data Objects: Next generation data programming in the Java environment JSF Central JavaServer Faces Sun Web site To learn more, visit the developerWorks WebSphere Studio zone and the developerWorks WebSphere Application Server zone. You'll find technical documentation, how-to articles, education, downloads, product information, technical support resources, and more. Developer Bookstore. Hundreds of technical books for developers at up to 35% off retail. WebSphere forums. Product-specific forums where you can ask questions and share your opinions with other WebSphere users. developerWorks blogs. Ongoing, free-form columns by software experts, with space for you to add your comments. q q q q q q q q q Download Description Download file 1 Download file 2 Download file 3 Name Size xyzinsurancetestclient_pi.zip 2.0 MB xsdsdotransform-feature.zip 52 KB xsd_sdo_soa_part3_listings.zip 4 KB Download method FTP | HTTP FTP | HTTP FTP | HTTP Information about download methods About the author Narinder Makin is a software engineer at IBM Research Triangle Part Lab in Durham, North Carolina. He is a developer of J2EE and SOA/SDO tools for the Rational Application Developer team. file:///C|/developerworks/pdf_0502/0502_makin/0502_makin.html (31 of 31) [2/23/2005 6:50:18 PM] IBM WebSphere Developer Technical Journal: from Roland Barcia IBM WebSphere Developer Technical Journal: from Roland Barcia Examining the EJB 3.0 Simplified API specification Level: Introductory Roland Barcia (barcia@us.ibm.com) Consulting IT Specialist, IBM 23 Feb 2005 A look at the latest draft of the EJB™ 3.0 Simplified API specification, what it may offer developers, and where there is still room for improvement. A couple of weeks ago, the Java™ Community Process (JCP) released an early second draft of the Enterprise JavaBeans™ (EJB) 3.0 specification under JSR 220, divided into three documents: q Contents: POJO and annotations Container services Callbacks Interceptors Dependency injection Annotations or deployment descriptors? Conclusion Resources About the author q q Rate this article EJB 3.0 Simplified API: Defines the new simplified API used to code Enterprise JavaBean Components, specifically session beans and Related content: message-driven beans. IBM WebSphere Developer Enterprise JavaBeans Core Contracts and Requirements: Defines Technical Journal the EJB contracts between the Bean and the EJB container. Persistence API: Defines the new Entity Bean model for persistence. In this column, I thought I would highlight some of the features in the EJB 3.0 Simplified API, and comment a bit on where I think improvements can be made. Since I will be addressing only the Simplified API, when speaking of EJB components, I will be referring to session beans and message-driven beans, not entity beans, since persistence is not covered under the Simplified API. The EJB specification has many goals, most of which I will not cover, but in brief: the EJB 3.0 specification is in-line with the overall goal of the J2EE™ 5.0 specification, which is to simplify the J2EE programming model. As such, this part of the specification is more along the lines of a cosmetic makeover rather than a set of functional enhancements. However, there are still a few things that the new programming model adds for developers, and I will mention these as we look at certain features. This article assumes some knowledge of the current EJB specification. POJO and annotations "POJO" (Plain Old Java Objects) is a term that has been thrown around a lot lately. It refers to code written as plain Java classes. Because EJB programs make you extend specific classes, provide several interfaces, and write deployment descriptors, they are viewed as overloaded Java objects that are no longer plain. file:///C|/developerworks/pdf_0502/0502_col_barcia/0502_col_barcia.html (1 of 8) [2/23/2005 6:50:22 PM] IBM WebSphere Developer Technical Journal: from Roland Barcia Instead, a developer needs a J2EE container to run and test them. I agree that coding POJOs without tools makes EJB development difficult. In the EJB 3.0 specification: q q q EJB components no longer require home interfaces. In addition, EJB components are no longer required to provide different interfaces or extend any specific EJB specific classes. J2SE 5.0 annotations are now a major facilitator for implementing EJB 3.0 components. By specifying special annotations, developers can create POJO classes that are EJB components. The class will be run through an annotations processor and the underlying container will provide the plumbing. EJB 3.0 introduces the notion of a Business Interface. An example is shown below: public interface Stock { public double getQuote(String symbol); } Your Bean class can implement the interface: @Stateless public class StockBean implements Stock public double getQuote(String symbol) { return 100.33; } } @Stateless annotation, above, means that this class is now a stateless session bean, and the business interface is used to invoke it. The early draft talks about allowing the possibility for the generation of Business Interfaces from the Bean class. A Stateless Session Bean can be coded without implementing a specific interface and annotation. An example is shown below: @Stateless public class StockBean public double getQuote(String symbol) { return 100.33; } } The annotation processor will then generate the Business Interface. By default, all methods that are file:///C|/developerworks/pdf_0502/0502_col_barcia/0502_col_barcia.html (2 of 8) [2/23/2005 6:50:22 PM] IBM WebSphere Developer Technical Journal: from Roland Barcia public and not injection methods are included in the Business Interface unless methods are specifically annotated. For example, if I specify at least one method with @BusinessMethod, then only the ones that are specified with @BusinessMethod are included in the Business Interface: @Stateless public class StockBean @BusinessMethod public double getQuote(String symbol) { return 100.33; } } Now that we have one interface, how do we specify whether a method is remote or local? Of course, we can use an annotation: @Stateless public class StockBean @Remote public double getQuote(String symbol) { return 100.33; } } You can annotate either the Business Interface or the Bean class itself. Enabling the annotation on the Bean class is useful when you choose to generate the Business Interface. How to specify whether or not a method should be invoked as a Web service is not mentioned in this EJB specification draft; this is instead being delegated to JSR 181, which defines annotations for Web services. Container services EJB components are popular because of the implicit support for transaction management and security. The EJB 3.0 specification will use annotations to apply container services. Here is an example of how you would specify a transactional attribute on a stateless session bean: file:///C|/developerworks/pdf_0502/0502_col_barcia/0502_col_barcia.html (3 of 8) [2/23/2005 6:50:22 PM] IBM WebSphere Developer Technical Journal: from Roland Barcia @Stateless public class StockBean { @TransactionAttribute(TransactionAttributeType.REQUIRESNEW) public double getQuote(String symbol) { return 100.33; } } The annotation means that the method will be run in a new transaction. Read the specification for more details on specific syntax and semantics of the different annotations. Container services can also be applied using deployment descriptors, although the current draft did not show how that would be specified. However, if both are used, the deployment descriptor would override the annotation. The final form of the specific annotations may change in future drafts. For example, certain annotations that are relevant to the J2EE specification as a whole may be factored out of EJB. Callbacks What about callbacks? Prior to the EJB 3.0 specification, developers had to implement callback methods such as ejbCreate() on the Bean class; Bean classes had to implement all the methods whether they used them or not. In most cases, these method implementations were empty. Callbacks are now handled through annotations. There are two mechanisms: callback methods and callback listener classes. Here is an example of how you would write code to respond to a callback using callback methods: @Stateless public class StockBean implements Stock public double getQuote(String symbol) { return 100.33; } @PostConstruct initializeCache() { } } The above code will now enable you to implement code after a bean instance is created. If I wanted to use a callback listener, I would create a Callback Listener class: file:///C|/developerworks/pdf_0502/0502_col_barcia/0502_col_barcia.html (4 of 8) [2/23/2005 6:50:22 PM] IBM WebSphere Developer Technical Journal: from Roland Barcia public class MyCallbackListener { @PrePassivate public clearCache(Object obj) { Stock stock = (Stock) obj; //perform logic } } A callback class that is not part of the Bean class has to take in a java.lang.Object parameter. The container will then pass the bean instance. A Bean class adds the callback listener class by using a special callback annotation at the Bean class level: @CallbackListener MyCallbackListener @Stateless public class StockBean implements Stock public double getQuote(String symbol) { return 100.33; } } Callbacks are nice because the inclusion of them in your code is conditional, unlike when you implement interfaces. The same could have been accomplished by adding a special abstract class with empty callbacks. In Appendix A of the specification, there is mention of providing special base classes for developers who wish to continue using the EJB 2.x style of development. Interceptors A nice addition to the EJB specification is the use of interceptors. One thing that was missing from EJB components is the ability to do pre/post-processing, much like servlet filters do for servlets. A developer can develop an Interceptor class and apply it to a bean. Here is an example of an interceptor that audits invocations of the StockBean class: file:///C|/developerworks/pdf_0502/0502_col_barcia/0502_col_barcia.html (5 of 8) [2/23/2005 6:50:22 PM] IBM WebSphere Developer Technical Journal: from Roland Barcia public class StockRequestAudit { @AroundInvoke public Object auditStockOperation(InvocationContext inv) throws Exception { try { Object result = inv.proceed(); Auditor.audit(inv.getMethod().getName(), inv.getParameters[0]); return result; } catch (Exception ex) { Auditor.auditFailure(ex); throw ex; } } } The Interceptor above intercepts the call to the target EJB method, then calls the proceed() method on the InvocationContext. This will enable the call to flow through to the actual EJB method that was invoked. After the target EJB method returns, it will use the metadata in the InvocationTarget to get the method name and parameters of the target EJB component that was called. The Interceptor can then be applied to the Bean class: @Stateless @Interceptors({StockRequestAudit}) public class StockBean implements Stock public double getQuote(String symbol) { return 100.33; } } Additionally, you can choose to develop interceptor methods that are implemented inside the Bean class, and also specify multiple interceptors, in which case the order in which they are called is specified by the order they are defined in the Bean class. Dependency injection What makes EJB development testing difficult are EJB code dependencies on thing slike data sources, as well as how EJB components are invoked by EJB clients. The EJB 3.0 specification introduces dependency injection as a mechanism to alleviate these difficulties. Instead of using JNDI lookups, an EJB can define a resource reference by injecting code. Below is an example of an EJB bean that needs to call another EJB component and use a data source to do JDBC work: file:///C|/developerworks/pdf_0502/0502_col_barcia/0502_col_barcia.html (6 of 8) [2/23/2005 6:50:22 PM] IBM WebSphere Developer Technical Journal: from Roland Barcia @Stateless public class StockBean implements Stock { @EJB(name="MarketBean", businessInterface="Market") Market market; @Resource(name="StockDB, resourceType="javax.sql.DataSource") DataSource stockDS public double getQuote(String symbol) { Connection con = stockDS.getConnection(); //DO JDBC work return market.getCurrentPrice(symbol); } } Dependency injection can occur in a variety of ways, for example, via a setter method or a class variable. See the specification for more details. Annotations or deployment descriptors? This current early draft of the EJB 3.0 specification has empty sections marked for the use of deployment descriptors as an alternative to annotations. But is the annotation approach better? Consider the name "deployment" descriptor, which implies that it describes elements of the application relevant to deployment. I can argue that many of the elements in the current EJB deployment descriptor are development artifacts, not deployment artifacts. So what elements would be better off in deployment descriptors? q q Elements that are likely to change when deployed, such as the mapping of a resource reference to an actual resource. Elements that apply globally to a group of EJB components. Annotations do a good job of specifying elements for a specific class, but elements that apply to many beans should be described outside. For example, I may want to apply a generic security role to a set of EJB components rather than an individual EJB component. Having one place to specify this is more productive than defining an annotation on every single EJB Bean class. Certain elements (transaction demarcation comes to mind) should be removed from deployment descriptors because they are not relevant to deployment. Allowing a deployer to override things such as transaction semantics would be quite dangerous. The JCP should keep these facts in mind for future iterations. Conclusion The second draft of the simplification API portion of the EJB specification is still very empty; the contracts portion of the specification is also missing from this early draft. I expect the core contracts will define things file:///C|/developerworks/pdf_0502/0502_col_barcia/0502_col_barcia.html (7 of 8) [2/23/2005 6:50:22 PM] IBM WebSphere Developer Technical Journal: from Roland Barcia such as how a resource reference defined in an annotation will get "mapped" to an actual data source defined on an application server, what happened to the Timer Service, and so on. Without seeing the core contracts, it is difficult to comment, so we'll save that for a future review. What should developers do today? Continue to use the current EJB specification, which will be fully supported by your J2EE application server vendor for quite some time. If you follow best practices, such as layering your application, changes can be applied with minimal effort. Acknowledgements Thanks to Wayne Beaton and Bobby Woolf for their suggestions for this commentary. Resources q EJB 3.0 specification Enterprise Java Programming with IBM WebSphere IBM WebSphere: Deployment and Advanced Configuration Enterprise JavaBeans (4th Edition) Purchase WebSphere books at discounted prices in the Developer Bookstore. q q q q About the author Roland Barcia is a Consulting IT Specialist for IBM Software Services for WebSphere in the New York/New Jersey metro area. He is a co-author of IBM WebSphere: Deployment and Advanced Configuration. file:///C|/developerworks/pdf_0502/0502_col_barcia/0502_col_barcia.html (8 of 8) [2/23/2005 6:50:22 PM] The EJB Advocate: Making entity EJB components perform The EJB Advocate: Making entity EJB components perform from the IBM WebSphere Developer Technical Journal Level: Introductory Geoff Hambrick (ghambric@us.ibm.com) Distinguished Engineer, IBM 23 Feb 2005 Using poorly designed EJB™ components can lead to serious performance problems during system testing or (worse) in production. The EJB Advocate shows how to design method signatures to minimize the "chattiness" between layers and get the most out of your EJBs. In each column, The EJB Advocate presents the gist of a typical back-and-forth dialogue exchange with actual customers and developers in the course of recommending a solution to an interesting design issue. Any identifying details have been obscured, and no "innovative" or proprietary architectures are presented. For more information, see Introducing the EJB Advocate. The problem Contents: The problem The good, the bad, and the ugly Hide the ugly behind a custom facade Conclusion Resources About the author Rate this article Related content: IBM WebSphere Developer Technical Journal Introducing the EJB Advocate Dear EJB Advocate, My first J2EE project was to build a Web application that renders products from our company catalog for customers to add to their shopping cart for purchase. I was a big advocate of object technology and the idea of entity EJBs. That is, until I started testing a prototype on my laptop using IBM® WebSphere® Studio Application Developer's test environment. To make a long story short, it took over five seconds for my servlet to load a page-worth of local entity EJBs for display. When I recoded the servlet to use JDBC, it took less than one second. I hate to say this, but sign me: No Longer a Fan It was pretty obvious right away that the entity EJB architecture was flawed because an apples-to-apples comparison of well designed CMP entity EJBs to hand-coded JDBC components has never shown this level of difference. However, there were some good things to point out about their focus on early testing to explore first in my reply. My thought was that by pointing out an extra test they could try, the team may be able to figure the problem out for themselves. file:///C|/developerworks/pdf_0502/0502_ejba/0502_ejba.html (1 of 13) [2/23/2005 6:50:28 PM] The EJB Advocate: Making entity EJB components perform Dear No Longer, It was good to see that you were using local versus remote entity EJBs, so that you didn't pay the additional performance penalty of remote method invocations. This overhead could have easily doubled the amount of time it took to load the page. One of the best practices associated with using entity EJBs is to always use local ones. We briefly discussed this approach in last month's column. I was also very happy to hear that you immediately built a prototype to test the performance of local entity EJBs versus directly-coded JDBC as the persistence layer. Many teams don't do candidate architecture performance testing until they build out the entire application, and ultimately end up with a lot of rework -- and maybe a critical situation -- in production. Others will attempt to hide the details of the persistence mechanism behind an "access bean" to make it easy to switch later, adding yet another layer to the system (both JDBC and entity EJBs are already abstractions of the persistence mechanism). I suspect I know what the problem is, but I'd like you to turn on tracing of the JDBC datasource to see how many SQL statements are getting executed (see the WebSphere Application Server Information Center). You can also turn on EJB tracing which, as Matt Oberlin points out in his Meet the Experts article, is pretty easy to do in WebSphere Studio Application Developer (Figure 1). Figure 1. Turning on EJB trace in WebSphere Studio Application Developer Further, and as Stacy Joines points out in her excellent book on WebSphere performance, gathering precise performance measurements is really important to finding and fixing bottlenecks. The reason I ask you to capture this more precise measure is that it is likely you will see many more SQL statements for the entity bean case than for the direct JDBC case, and that accounts for the difference in performance. In fact, I predict that you will see one SQL statement executed for each attribute read from each product entity, plus one! file:///C|/developerworks/pdf_0502/0502_ejba/0502_ejba.html (2 of 13) [2/23/2005 6:50:28 PM] The EJB Advocate: Making entity EJB components perform Let me know what you find out. OK then, Your EJB Advocate The good, the bad, and the ugly Dear EJB Advocate, How did you guess? I display up to ten products per page, with five attributes per product (SKU, description, price, a link to an image, and a date when the item will be available). I ended up with fifty-one SQL statements executed for the entity EJB case and only one SQL statement for the direct JDBC case! It is no wonder that the entity EJBs did not come anywhere close to the performance. It seems like I made the right choice to go with JDBC. Sign me still: No Longer a Fan I had hoped that the SQL trace data would make it obvious what the problem was -- that "No Longer" would no longer rely on imprecise "stopwatch" measurements, and would try to find the cause of the difference or problem before giving up. Helping someone get over disillusionment is harder than I thought! Here was my reply: Dear No Longer, I suspect that you are invoking your entities outside the scope of a global transaction, which will cause each call to an entity to be executed in a separate transaction and result in its own SQL statement (depending on your deployment options). Specifically, there will be one call to the home for the finder returning the next ten entities, and five calls to each entity for the get() methods associated with the attributes displayed. Calling entities outside of a global transaction is definitely a "worst" practice (more commonly called an anti-pattern). In fact, it is so important to avoid calling entities outside of a transaction that some EJB developers suggest (as this EJB Advocate does) to declare transactions to be "mandatory" in the EJB deployment descriptor: use the Mandatory within the tag. This declaration will cause an exception to be thrown, if there is not already a transaction scope initialized when the entity is accessed. There are two ways to wrap logic that may be calling entity EJBs in a global transaction and greatly improve performance. One is the "easy way" and one is the "right way.". The easy way is to explicitly add code to your servlet to start and end a global transaction around the calls to the EJBs, like so: file:///C|/developerworks/pdf_0502/0502_ejba/0502_ejba.html (3 of 13) [2/23/2005 6:50:28 PM] The EJB Advocate: Making entity EJB components perform ... import javax.transaction.*; ... public class YourServlet implements HttpServlet { private InitialContext initCtx = new InitialContext(); public void doGet ( HttpServletRequest req, HttpServletResponse ){ UserTransaction userTran = (UserTransaction)initCtx.lookup( "java:comp/UserTransaction" ); userTran.begin(); //Use entity to load data ... userTran.commit(); } ... } Some teams go a little further and create a superclass servlet to handle this behavior using a technique called template inheritance. The superclass would be declared abstract . Its doGet() method would be declared final and would call down to an abstract doGetYourParent() method implemented by YourServlet (the ones inheriting that behavior). The parent class code might look like the following: ... import javax.transaction.*; ... public abstract class YourParentServlet implements HttpServlet { private InitialContext initCtx = new InitialContext(); public final void doGet ( HttpServletRequest req, HttpServletResponse ){ UserTransaction userTran = (UserTransaction)initCtx.lookup( "java:comp/UserTransaction" ); userTran.begin(); doGetYourParent(); userTran.commit(); } protected abstract void doGetYourParent( HttpServletRequest req, HttpServletResponse ); ... file:///C|/developerworks/pdf_0502/0502_ejba/0502_ejba.html (4 of 13) [2/23/2005 6:50:28 PM] The EJB Advocate: Making entity EJB components perform } The changes required to your subclass servlets in order to use template inheritance are pretty simple: a. Change the implements clause of YourServlet class from HttpServlet to YourParentServlet, and b. Change the name of its doGet(), doPost() and other HttpServlet methods to doYourParent(). One major benefit of the template inheritance approach is it makes it easy to consistently and transparently add qualities of service, like transaction start and stop, cache checking, error handling, and other behaviors, that your team will likely want to include to ensure robustness. Regardless of your approach to starting a global transaction, you should notice a drastic drop in the number of SQL statements in the trace (depending on the access intents and other deployment options; see the WebSphere Application Server Information Center on how to set attributes like the Collection Increment to the number you would like to read -ten in your case). But even if you make these changes and eliminate all the places where CMPs are called outside of the scope of a global transaction, a load analysis tool (one that measures the performance of the system under near production conditions), like IBM Rational® Performance Tester, will still show a significant difference between the throughput and CPU utilization of JDBC and entity EJB code, even if profiling tools like JInsight and path analysis tools like IBM Tivoli® Monitoring for Transaction Performance do not show a difference. The "right way" to fix the code depends on the details of your design. You may already be pretty close, so let me ask you a question: are you using a JavaServer™ Page to render the page from a "data transfer object" (a POJO with get/set methods only) loaded by the servlet (a J2EE best practice)? Or does the servlet render the HTML reply directly? OK then, Your EJB Advocate Hide the ugly behind a custom facade Dear EJB Advocate, You are right that I used a JSP to render the page following the Model 2 approach. In other words, the servlet loads an array of up to ten "ProductView" objects (which is the same as your data transfer object except that it is Serializable), and then calls the JSP. Just to be clear, here is the relevant code in the servlet, written in the style you suggested in your previous reply: file:///C|/developerworks/pdf_0502/0502_ejba/0502_ejba.html (5 of 13) [2/23/2005 6:50:28 PM] The EJB Advocate: Making entity EJB components perform ... import javax.transaction.*; ... public class YourServlet implements HttpServlet { private InitialContext initCtx = new InitialContext(); public void doGet ( HttpServletRequest req, HttpServletResponse ){ UserTransaction userTran = (UserTransaction)initCtx.lookup( "java:comp/UserTransaction" ); userTran.begin(); ProductLocalHome home = (ProductLocalHome)initCtx.lookup( "java:comp/env/ProductLocal" ); Collection products = home.findNextNFrom(last, count); int size = 0; ProductView[] results = new ProductView[products.size]; Iterator i = products.iterator(); ProductView product = null; while (i.hasNext()) { ProductLocal product = (ProductLocal)i.next(); ProductView result = new ProductView(); // Each of these used to cause a tran and SQL result.setSku(product.getSku()); result.setDesc(product.getDesc()); result.setPrice(product.getPrice()); result.setImage(product.getImage()); result.setData(product.getDate()); results[size++] = result; } // Set into the HttpServletRequest req.setAttribute("ProductView", results); // Invoke the ProductView JSP (not interesting here) ... userTran.commit(); } ... } By the way, the JSP uses a custom tag to navigate through an array of ProductView objects (actually this tag navigates through an array of any kind of object simulating the "bean tag"), from which the "bean property tags" can be used to substitute the properties. I hope this is enough detail. file:///C|/developerworks/pdf_0502/0502_ejba/0502_ejba.html (6 of 13) [2/23/2005 6:50:28 PM] The EJB Advocate: Making entity EJB components perform I was glad to find that this "easy way" code actually brought the performance of entity EJBs close to that of JDBC (as measured by JInsight). I also used the "mandatory" CMT attribute, which verified that this took care of all the calls to the CMP outside of a transaction, However, using JDBC was still significantly better in a head-to-head comparision using our load testing tool (we use LoadRunner now, but will take a look at the Rational Performance Tester you mentioned.) Thanks, but I am still signed, No Longer a Fan This time, I got more than I had hoped for. No Longer provided code samples, which are far more precise than descriptions or block diagrams. And it seemed like they took the hint to use more precise measures of system performance using load and path analysis tools. If No Longer had intermixed the HTML rendering code (the view) with that to retrieve the data, I would have wanted to delve into servlet best practices (not a stretch, since I am an all around J2EE Advocate, too). I would have had to explain the best practice to use data transfer objects to flow data from the servlet to the JSP. The code that I include in my reply below would not have looked so familiar to No Longer. Dear No Longer, Thanks for the code sample. I much prefer that to any other form, since code is where the "rubber meets the road" with respect to performance. Nothing beats a static analysis to see if the design follows best practices. Together with load and path analysis, you get a pretty complete picture of how to find and fix the bottlenecks. It is great that you are following Model 2 best practices and have gone a step farther to provide a custom navigation tag for arrays. It is also great that you are already using data transfer objects, basically the same as Service Data Objects. Having this architecture makes the "right way" to get a global transaction the "easiest way" as well. In other words, you can create a session facade EJB to encapsulate the logic associated with gathering the data for the page (the array of ProductView objects). This pattern is discussed in last month's column, as well as in Kyle Brown's book (see Resources), among others. The session facade might look something like this: extends SessionBean { public ProductView[] getCatalog ( ProductKey lastKey, int count ){ ProductLocalHome home = (ProductLocalHome)initCtx.lookup( "java:comp/env/ProductLocal" ); // This call used to cause a trans and SQL Collection products = home.findNextNFrom(last, count); int size = 0; ProductView[] results = new ProductView[products.size]; Iterator i = products.iterator(); ProductView product = null; file:///C|/developerworks/pdf_0502/0502_ejba/0502_ejba.html (7 of 13) [2/23/2005 6:50:28 PM] The EJB Advocate: Making entity EJB components perform while (i.hasNext()) { ProductLocal product = (ProductLocal)i.next(); ProductView result = new ProductView(); // Each of these used to cause a tran and SQL result.setSku(product.getSku()); result.setDesc(product.getDesc()); result.setPrice(product.getPrice()); result.setImage(product.getImage()); result.setData(product.getDate()); results[size++] = result; } // Instead of setting into the HttpServletRequest return results; } ... } As you might notice in the example above, a benefit of using the Model 2 architecture with data transfer objects is that most of the logic in your servlet doGet() method simply moves into the session facade getCatalog() method. A major benefit of this move is that the logic to get the next page of products is now usable outside of the context of a servlet (like from within a message-driven bean, or another EJB). A remote interface can be provided as well (automatically generated by tooling in WebSphere Studio Application Developer), making it available from a J2EE client. The use of the data transfer object minimizes the chattiness between the layers -- only one stateless call is needed. In any event, the servlet no longer needs to deal with a transaction. It looks something like: ... public class YourServlet implements HttpServlet { private InitialContext initCtx = new InitialContext(); public void doGet ( HttpServletRequest req, HttpServletResponse ){ MySessionLocalHome home = (MySessionLocalHome)initCtx.lookup( "java:comp/env/MySession" ); // Get the last key field as before ProductView[] home.create().getProductView(last, 10); //Load array into HttpServletRequest and invoke JSP ... } ... } I know it seems like this best practice trades code to start and end a transaction with code to invoke an EJB method, but there are a couple of additional benefits beyond the ability to reuse the logic in other situations. First, the local file:///C|/developerworks/pdf_0502/0502_ejba/0502_ejba.html (8 of 13) [2/23/2005 6:50:28 PM] The EJB Advocate: Making entity EJB components perform session reference can be cached in the servlet init() method to eliminate the lookup in the doGet(). Second, and most importantly, handling transactions can be very complex, especially where exceptions are concerned. Improper handling can lead to "leaks" that result in their own kind of performance problems. In short, another best practice is to use container managed transactions wherever possible. Regardless, this "right way" code will run essentially as fast as the "easy way" code (given that a local session interface is used). But the problem will still remain that the end-to-end performance using a local entity will still perform significantly worse than when using JDBC (now behind the session EJB, which effectively encapsulates the model from the view). The reason is that even though the get() methods on the entity are local, there is still a lot of overhead to check for security and transactions. Some estimates of this overhead place it around ten thousand instructions, which for this example would be insignificant when measured by a path analysis tool: 50 x 10000 = 500000 total. But what if the "count" above were 100 and the number of properties accessed was 100. The total number of instructions is 100 million, which is starting to be a measurable difference. This phenomenon associated with "scale" is why load testing is best to find real performance differences. Path testing lets you find the likely culprit with which you can follow up with static analysis (a code review). In this case, the number of instructions it takes to access a property on a data transfer object is estimated in the 10s, not 10s of thousands -- orders of magnitude better than accessing even a local EJB under a global transaction. The key to optimal EJB performance is to use data transfer objects and custom methods to create, get, and set all the needed properties for a given use case in one call. This minimizes the chattiness between the session facade and entity EJB. In general, it is possible to design your entity EJBs with the right set of methods such that a user need only make one call after a find -- either a create, retrieve, update, or delete method. The following code illustrates what the entity EJB would look like with a custom get: public abstract ProductBean extends EntityBean { // Here are the properties needed for the custom method // NOW NO LONGER ON INTERFACE TO PREVENT INDIVIDUAL ACCESS public abstract ProductKey getSku() ; public abstract void setSku(ProductKey value); public abstract String getDesc() ; public abstract void setDesc(String value); public abstract BigDecimal getPrice() ; public abstract void setPrice(BigDecimal value); public abstract String getImage() ; public abstract void setImage(String value); public abstract Date getDate () ; public abstract void setDate(Date value); // Probably more properties than these above // Here is the custom get method& public ProductView getProductView ( ){ ProductView result = new ProductView(); // Now cannot cause a tran and SQL result.setSku(getSku()); result.setDesc(getDesc()); result.setPrice(getPrice()); file:///C|/developerworks/pdf_0502/0502_ejba/0502_ejba.html (9 of 13) [2/23/2005 6:50:28 PM] The EJB Advocate: Making entity EJB components perform result.setImage(getImage()); result.setDate(getDate()); return result; } ... } To enforce the use of the custom methods, many EJB designers only expose custom methods on the interface, like the following: public interface Product extends EJBLocalObject { public ProductView getProductView (); public void setProductView(ProductView value); } The home would have the custom creates and finds: public interface ProductHome extends EJBLocalHome { public Product create(ProductView value); public Collection findNextNFrom(ProductKey last, int count); } You might have noticed that I did not use "Local" as part of the entity EJB interface name (for either the home or the bean). Since I never expose a remote interface to an entity EJB, it seems like overkill to add length to the class name. In any event, the session facade would change as follows to exploit these custom methods: public class YourSession extends SessionBean { public ProductView[] getCatalog ( ProductKey lastKey, int count ){ ProductHome home = (ProductHome)initCtx.lookup( "java:comp/env/ProductLocal" ); // This call used to cause a trans and SQL Collection products = home.findNextNFrom(last, count); int size = 0; ProductView[] results = new ProductView[products.size]; Iterator i = products.iterator(); ProductView product = null; while (i.hasNext()) { // Treat a next on an iterator of entities like a find Product product = (Product)i.next(); file:///C|/developerworks/pdf_0502/0502_ejba/0502_ejba.html (10 of 13) [2/23/2005 6:50:28 PM] The EJB Advocate: Making entity EJB components perform // Now only one call after find, which is the ideal results[size++] = product.getProductView(); } // Instead of setting into the HttpServletRequest return results; } ... } Note that we simply moved the code that was in the loop of the session EJB getCatalog() method into the entity EJB getProductView() method; then we replaced the moved code with a single method call. If you load test the code implemented in this manner, you will likely notice a much more reasonable overhead of using entity EJBs with respect to JDBC. Given that entity EJBs will be far more maintainable than JDBC, the tradeoff will be well worth it. And just for future reference, here is a UML diagram showing the general end-to-end architecture. It shows the relationship between JSPs and servlets, session and entity EJBs, and key and view data transfer objects: Figure 2. UML diagram showing end-to-end architecture I hope this discussion helps to renew your enthusiasm for entity EJBs. At the very least, I hope you have some new tools and techniques for precisely measuring the performance differences and evaluating the tradeoffs. OK then, Your EJB Advocate Conclusion Through this exchange, we saw why using a session facade in front of a local entity EJB is so important to ensure that only one transaction is executed per UI event, and to minimize the number of SQL calls sent to the database. Just as significant, we saw the importance of using a data transfer object (now being called an SDO) and custom methods on entity EJBs to minimize the file:///C|/developerworks/pdf_0502/0502_ejba/0502_ejba.html (11 of 13) [2/23/2005 6:50:28 PM] The EJB Advocate: Making entity EJB components perform chattiness between layers, even when the local interface is used. And, incidentally, we saw that using an SDO enables you to flow data all the way from the entity to the JavaServer Page rendering the HTML, passing through the session facade and the servlet (the model and view controllers respectively). We discussed how template inheritance can be used to add behaviors (like starting and committing a global transaction) transparently to the servlet code. Even though the use of session facade minimizes the need for this approach, template inheritance in servlets may still be useful in cases where it calls more than one session EJB in the context of the doGet() or doPost(). We also discussed declaring transactions on entity EJBs to be mandatory, as well as not exposing the individual CMP attributes to the entity interface. Both of these best practices help to enforce your usage policies. One process (rather than design) best practice we covered was related to measuring performance using load and path analysis tools, then analyzing the code and configuration to find and fix bottlenecks. The idea is to use tools like Rational Performance Tester, Tivoli Monitoring for Transaction Performance, and JInsight that capture number of calls, the amount of data passed back and forth, and the amount of time that each call takes. Also, we hinted at a best practice that static analysis should be based on code, not on class or high level sequence diagrams (even though these are useful to get an overview). What's next... If you have an interesting problem associated with using EJBs of any type, please feel free to contact the EJB Advocate. Otherwise, in the next column,we will examine Service Data Objects, and how EJBs (both entities and sessions) will play a role within a Service Oriented Architecture. Resources q The EJB Advocate: Getting EJB cross references right Java 2 Platform, Enterprise Edition (J2EE) specification, the definitive source Enterprise Java Programming with IBM WebSphere, Second Edition, by Kyle Brown, Gary Craig, Greg Hester, Russell Stinehour, W. David Pitt, Mark Weitzel, JimAmsden, Peter M. Jakab, Daniel Berg. Foreword by Martin Fowler. Performance Analysis for Java Websites, by Stacy Joines, Ruth Willenborg, and Ken Hygh. IBM Rational Performance Tester IBM Tivoli Monitoring for Transaction Performance WebSphere Application Server Information Center Meet the Experts: Matt Oberlin on WebSphere Studio Application Developer Purchase WebSphere books at discounted prices in the Developer Bookstore. q q q q q q q q About the author Geoff Hambrick is a lead consultant with the IBM Software Services for WebSphere Enablement Team and lives in Round Rock, Texas (near to Austin). The Enablement Team generally helps support the pre-sales process through deep technical briefings and short term Proof of Concept engagements. Geoff was appointed an IBM Distinguished Engineer in March of 2004 for his work in creating and disseminating best practices for developing J2EE applications hosted on IBM WebSphere Application Server. file:///C|/developerworks/pdf_0502/0502_ejba/0502_ejba.html (12 of 13) [2/23/2005 6:50:28 PM] The EJB Advocate: Making entity EJB components perform file:///C|/developerworks/pdf_0502/0502_ejba/0502_ejba.html (13 of 13) [2/23/2005 6:50:28 PM]

Related docs
Other docs by mmm3
PETTY CASH REGISTER
Views: 658  |  Downloads: 39
Job description form list
Views: 922  |  Downloads: 45
Code of Ethics for Homeopathy
Views: 401  |  Downloads: 13
MONTHLY CALENDAR TEMPLATE
Views: 854  |  Downloads: 13
Employment Offer Letter Exempt Employee
Views: 878  |  Downloads: 18
Independent Contractor Agreement
Views: 490  |  Downloads: 31
Sample Open-Ended Promissory Note
Views: 2552  |  Downloads: 21
Information release authorization
Views: 345  |  Downloads: 7