Meet the experts: Matthew Oberlin on WebSphere Studio Application Developer

This question and answer article features Matthew Oberlin, IBM Software Services consultant for WebSphere Studio Application Developer, who answers top questions from WSDD users.

Matthew Oberlin (mao@us.ibm.com), Software Services Consultant , IBM Pittsburgh, Pennsylvania

Matthew Oberlin is a Software Services Consultant in IBM Pittsburgh, Pennsylvania



18 September 2003

Photo: Matthew Oberlin

This month we ask IBM ® Software Services consultant Matthew Oberlin to answer your questions about WebSphere® Studio Application Developer. Matt splits his time between educating the services team and mentoring customers on the most effective and efficient ways to develop J2EE applications for WebSphere. Some of Matt's favorite topics are: implementing best practices for EJBs, the importance of logging applications, using ANT for building WebSphere applications, and using SCM with WebSphere Studio. Recently Matt has been working with the WebSphere Studio family of products to implement Web services. For more information on WebSphere Studio, see WebSphere Studio Zone.

Matt would like to thank his team members in the IBM Software Services for WebSphere organization. In particular, Matt would like to thank Pete Van Sickel, Scott Karabin, Key Botzum, Vinod Jessani, and Roland Barcia. If you need skilled help with WebSphere, see the Software Services for WebSphere Web site.

Question: How can I install a Portal Toolkit for WebSphere Portal 5.0 into WSAD 5.1? (submitted by MK)

Answer: WebSphere Portal ships with WebSphere Studio Site Developer 5.0 and WebSphere Portal runtime sits on top of WebSphere Application Server 5.0.1. It is important to remember that WebSphere Studio 5.1 gets its version number from Eclipse. WebSphere Studio 5.1 uses WebSphere Application Server 5.0.2 as the J2EE application test environment. The formula is Studio# = Eclipse# + 3. One of the most recent version of Eclipse is 2.1, and this is the basis for WebSphere Studio 5.1.

I certainly don't speak for development, but there are differences that would require changes to the Portal Toolkit to get it to run on WebSphere Studio 5.1. At this point in time, the Portal Toolkit will not install on WebSphere Studio Application Server 5.1. Keeping in mind that there will always be some version skew in a product base as large as WebSphere, I think the Portal Toolkit is right where it should be.

Question: WebSphere Studio gets errors on generated deploy codes while there is no errors in the tasks view. What do you have to tell us about that and don't you think so it is better to hide the generated deploy codes from the developer? (submitted by Pasha Golshani)

Answer: It is difficult to find the cause of the errors in generated code without knowing the exact errors. Double-check your task list and make sure you have not filtered out any errors. The top left corner of the task list says "Tasks (Filter matched x of y items)", if you are filtering the items on the task list view. Also look for any warnings in the task view, not just errors. You may be able to figure out what is happening by looking more closely at the errors in the generated code. If your EJBs are entity beans, look at the Container Managed Persistence (CMP) mapping. Delete the mapping and remap the EJBs from scratch.

As far as hiding the generated code for EJBs, I would be disappointed if WebSphere hid the generated code or did not provide the source code for the generated EJB classes. From the beginning, the EJB specification has assumed that there is container specific code generated for Enterprise Java Beans. Most of the time, I don't care what this generated code is or what it looks like. However, when I do want to know what is happening "under the covers", I cannot see this without the source code for the generated EJB classes.

One common scenario that I'd like to see is the SQL that is being generated for Entity EJBs. Note: Don't change this SQL, just look, to better understand what the container is doing. In WebSphere Studio 5.1, I can look in MyCustomerBeanFunctionSet_4f50351f.java, where MyCustomerBean is the name of my entity bean and 4f50351f is generated by the container. I can see the JDBC that is running for this EJB. If I really want, I can put in a breakpoint and step through this code.

If you are still having problems with errors in generated code, please call the IBM support organization. They will be happy to assist you.

Question: How do I add a library path to the server/server config runtime environment to run a class? Path and library path are the same on the Windows® environment. (submitted by Shiva)

Answer: I find that many users are confused about the use of Java classpaths in WebSphere Studio. Within WebSphere Studio, there are two categories of class paths that you need. The first is obvious, the classpath used for compilation. In Eclipse and WebSphere Studio, this is called the Java Build Path.

The second classpath is the WebSphere Application Server runtime classpaths. Note that other servers, such as Apache Tomcat, also have runtime classpaths. The principals are the same for all Java Application Servers, so I'll focus on WebSphere. You also mention path, as in the environment variable for executables. Don't worry about the path. Once the Java Virtual Machine starts up, we no longer care about the path.

Let's take a look at the Java Build Path for one of my projects with WebSphere Studio.

Figure 1. Java Build Path - Libraries
Java Build Path - Libraries

Right-click on the project and select Properties. In this view, we are looking at the Libraries tab. Notice there are three categories of resources listed here. First, log4j1.2.6.jar is a jar file inside of my Enterprise Application Archive (EAR) project. The next is the java runtime jar. This was added by WebSphere Studio when I created this project. The last several entries are all jar files that are in the runtime library of the WebSphere Application Server. Aha! It is interesting to note that I need these here so that my Java types will compile.

I won't have to do a thing for my server. These jars will be available to my classes inside of WebSphere Application Server. Keep this in mind. You will often have to add WebSphere or J2EE specific jars to the build classpath of your project to compile. The file j2ee.jar contains all of the J2EE servlet, EJB, APIs, and so on. For Web projects and EJB projects, WebSphere Studio adds this jar for me. On the other hand, I have to add this jar to Java projects that make use of the J2EE APIs. When I click on the Projects tab, this project references classes in two other projects. Anyone who remembers VisualAge® for Java may remember that everything inside the workspace could see everything else. This is not true for Eclipse and WebSphere Studio. I have to explicitly mark which projects are used by this project.

Figure 2. Java Build Path - Projects
Java Build Path - Projects

At this point you are asking, what about the runtime classpath for other projects? Good question. We need to know a little more about the project we using here. We have been looking at the build classpath for a Web project (called OnlineMallWeb) that is part of a J2EE application. This application has a jar file full of classes that were given to us, log4j-1.2.6.jar. This is just a set of classes, we don't need or want the source so it goes in the EAR file. Within WebSphere Studio, this jar file goes in the Enterprise Application Project.

You see the reference to this log4j-1.2.6.jar in Figure 1. I also have another jar file that has some utility classes that I have written and periodically update. I want the source for these. In this case, I created a Java Project called OnlineMallUtils and I marked it as part of my J2EE application. When my J2EE application is eventually deployed, it is important to note that the log4j jar and the OnlineMallUtils will look the same. They are both part of my application, as an added bonus they will both be available to the classes in my OnlineMallWeb module at runtime. The other project listed on this tab is the OnlineMallEJB project. By default, in WebSphere Application Server 5.0.x, classes in the Web modules can see classes in EJB modules. So far, so good.

A few more points about the runtime classpaths. The best place to put classes for a J2EE application is inside the EAR file that is deployed. For more information on why it is so important to put as much as possible inside the EAR file, see J2EE Packaging and Common Code.

Figure 3. The MANIFEST.MF File
The MANIFEST.MF File

Now let me finish the story about how my Web project, OnlineMallWeb, can see the jar files, log4j jar, and OnlineMallUtils at runtime. Take a look at Figure 4. If I double click on the MANIFEST.MF file, I see the editor.

Figure 4. JAR Dependency Editor
JAR Dependency Editor

There is a shortcut inside of WebSphere Studio. If I add these dependencies in the MANIFEST file first, they are added to my build classpath as shown previously. For the run time classpaths of your Application Server, open up the server configuration and click on the Environment tab. You see two places that you can add jars, directories, and so on to the classpath of the application.

Figure 5. Runtime Classpaths for WebSphere Application Server
Runtime Classpaths for WebSphere Application Server

Anything that you want to make available to the Java Virtual Machine for all the application running inside of this server should be added to the top entry, ws.ext.dirs. This extends the classes that are loaded by the WebSphere runtime and made available to your applications. Avoid using the bottom "Class Path" entry. This adds classes that are loaded before the WebSphere classes, such as J2EE.jar. In most cases, this makes the Class Path entries useless.

The rule for classpaths and classloaders is "Keep it Simple." For J2EE, the rule is "Put everything your application needs in the EAR file." For more information, see the WebSphere 5.0 InfoCenter and search for "Classloaders."

You should also search the WebSphere Studio online help for "class loading." Use the quotes to help the expedite the search. One particularly useful entry is entitled "Class Loading: Resources for Learning." It gives you pointers to classloaders and classpaths.

Question: We have developed an Ear file containing CMP 2.0 beans with CMR in WSAD 5.1 and DB2® Connect Ver 7.2 FP 9 connected to DB2 6.1 running on the mainframe. We ported this application to WSAD 5.0 and DB2 Connect Ver 7.2 FP 7. DB2 6.1. A different database was used. After deploying the code, it gives a runtime error while creating an entity bean. (submitted by S. Mohanavelu)

Click to see code listing

------------------------------------- 
In console, stack trace (only a part)is as follows 
------------------------------------ 
was.install.root = C:\IBM\WSAD\runtimes\base_v5 
user.install.root = C:\IBM\WSAD\runtimes\base_v5 
Java Home = C:\IBM\WSAD\runtimes\base_v5\java\jre 
ws.ext.dirs = C:\IBM\WSAD\runtimes\base_v5/java/lib;C:\IBM\WSAD\runtimes\base_v5/classes; 
C:\IBM\WSAD\runtimes\base_v5/classes; 
C:\IBM\WSAD\runtimes\base_v5/lib;C:\IBM\WSAD\runtimes\base_v5/lib/ext; 
C:\IBM\WSAD\runtimes\base_v5/web/help; 
C:\IBM\WSAD\runtimes\base_v5/deploytool/itp/plugins/com.ibm.etools.ejbdeploy/runtime; 
C:/Program Files/SQLLIB/java/db2java.zip; 
C:/IBM/WSAD/wstools/eclipse/plugins/com.ibm.etools.webservice_5.0.1/runtime/worf.jar 
Classpath = C:\IBM\WSAD\runtimes\base_v5/properties;C:\IBM\WSAD\runtimes\base_v5/properties; 
C:\IBM\WSAD\runtimes\base_v5/lib/bootstrap.jar; 
C:\IBM\WSAD\runtimes\base_v5/lib/j2ee.jar;C:\IBM\WSAD\runtimes\base_v5/lib/lmproxy.jar; 
C:/IBM/WSAD/wstools/eclipse/plugins/com.ibm.etools.websphere.tools.common_5.0.1/runtime/wteServers.jar; 
C:/IBM/WSAD/wstools/eclipse/plugins/com.ibm.etools.websphere.tools.common_5.0.1/runtime/wasToolsCommon.jar 
Java Library path = C:\IBM\WSAD\runtimes\base_v5/bin;C:\IBM\WSAD\runtimes\base_v5/java/bin; 
C:\IBM\WSAD\runtimes\base_v5/java/jre/bin;C:\IBM\WSAD\eclipse\jre\bin;.;C:\WINDOWS\System32;C:\WINDOWS; 
C:\WINDOWS\system32; 
C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\Program Files\PC-Doctor for Windows\services; 
C:\Program Files\SQLLIB\BIN;C:\Program Files\SQLLIB\FUNCTION;C:\Program Files\SQLLIB\SAMPLES\REPL; 
C:\Program Files\SQLLIB\HELP;C:\PROGRA~1\IBM\IMNNQ 
************* End Display Current Environment ************* 
[9/20/03 6:33:18:514 PDT] 5ed91356 ManagerAdmin  I TRAS0017I: The startup trace state is *=all=disabled. 
[9/20/03 6:33:19:342 PDT] 5ed91356 AdminInitiali A ADMN0015I: AdminService initialized 
: 
: 
[9/20/03 6:33:44:187 PDT] 5ed91356 WsServer      A WSVR0001I: Server server1 open for e-business 
[9/20/03 6:34:02:032 PDT] 4c455343 WebGroup      I SRVE0180I: [WSPOCWeb] [/WSPOCWeb] [Servlet.LOG]:  
	/index.jsp: init 
[9/20/03 6:34:02:516 PDT] 4c455343 SystemOut     O [Domain Controller] CONSTRUCTOR 
[9/20/03 6:34:08:188 PDT] 4c455343 SystemOut     O LLOKED UP 
[9/20/03 6:34:12:079 PDT] 4c455343 DataAccessReq E PMGR6022E: Error using adapter to create or  
	execute an Interaction. ??? 
[9/20/03 6:34:12:142 PDT] 4c455343 DataAccessReq E PMGR0000E: Call stack: 
com.ibm.ws.ejbpersistence.utilpm.PersistenceManagerException: PMGR6022E: Error using adapter to create  
	or execute an Interaction. ??? 
at com.ibm.ws.ejbpersistence.dataaccess.DataAccessRequestImpl.execute(DataAccessRequestImpl.java:159) 
at com.ibm.ws.ejbpersistence.beanextensions.CBStatefulPersistor.executeCreate(CBStatefulPersistor.java:229) 
at com.ibm.ws.ejbpersistence.beanextensions.CBNotExistState.ejbCreate(CBNotExistState.java:38) 
at com.ibm.ws.ejbpersistence.beanextensions.CBStatefulPersistor.ejbPostCreate(CBStatefulPersistor.java:94) 
at com.ibm.ws.ejbpersistence.beanextensions.ConcreteBeanStatefulInstanceExtensionImpl.ejbPostCreate 
	(ConcreteBeanStatefulInstanceExtensionImpl.java:133) 
at com.wiredscholar.persistence.ConcreteUser_a3d0e315.ejbPostCreate(ConcreteUser_a3d0e315.java:149) 
at com.wiredscholar.persistence.EJSCMPUserHomeBean_a3d0e315.create_Local(EJSCMPUserHomeBean_a3d0e315.java:39) 
at com.wiredscholar.persistence.EJSLocalCMPUserHome_a3d0e315.create(EJSLocalCMPUserHome_a3d0e315.java:24) 
at com.wiredscholar.bizlogic.registration.RegDomainController.<init>(RegDomainController.java:68) 
at java.lang.Class.newInstance0(Native Method) 
: 
: 
---- Begin backtrace for nested exception 
java.lang.AbstractMethodError: COM/ibm/db2/jdbc/app/DB2Connection.prepareStatement 
at com.ibm.ws.rsadapter.spi.WSStatementCache.reallyPrepareStatement(WSStatementCache.java:360) 
at com.ibm.ws.rsadapter.spi.WSStatementCache.getPreparedStatement(WSStatementCache.java:145) 
at com.ibm.ws.rsadapter.spi.WSRdbManagedConnectionImpl.getPreparedStatement 
(WSRdbManagedConnectionImpl.java:1157) 
at com.ibm.ws.rsadapter.cci.WSResourceAdapterBase.prepareStatement(WSResourceAdapterBase.java:136) 
at com.wiredscholar.persistence.websphere_deploy.DB2UDBOS390_V6_1.UserBeanFunctionSet_a3d0e315.Create 
	(UserBeanFunctionSet_a3d0e315.java:35) 
at com.wiredscholar.persistence.websphere_deploy.DB2UDBOS390_V6_1.UserBeanFunctionSet_a3d0e315.execute 
	(UserBeanFunctionSet_a3d0e315.java:1238) 
at com.ibm.ws.rsadapter.cci.WSInteractionImpl.execute(WSInteractionImpl.java:156) 
at com.ibm.ws.rsadapter.cci.WSRelationalRAAdapter.executeCreate(WSRelationalRAAdapter.java:179) 
at com.ibm.ws.ejbpersistence.dataaccess.DataAccessRequestImpl.execute(DataAccessRequestImpl.java:86) 
at com.ibm.ws.ejbpersistence.beanextensions.CBStatefulPersistor.executeCreate(CBStatefulPersistor.java:229) 
at com.ibm.ws.ejbpersistence.beanextensions.CBNotExistState.ejbCreate(CBNotExistState.java:38) 
at com.ibm.ws.ejbpersistence.beanextensions.CBStatefulPersistor.ejbPostCreate(CBStatefulPersistor.java:94) 
at com.ibm.ws.ejbpersistence.beanextensions.ConcreteBeanStatefulInstanceExtensionImpl.ejbPostCreate 
	(ConcreteBeanStatefulInstanceExtensionImpl.java:133) 
</init>

Answer: This is a rather difficult problem to debug remotely. I don't have a quick answer to the problem you are seeing here. Based on everything you have told me, I don't know of any reason why this does not work. There are several places I can suggest to look at. First, double check the JDBC and datasource driver. The key piece of information in the stack trace you provided is PMGR6022E. You can search for this error in the WebSphere InfoCenter. I found the following:

Click to see code listing

PMGR6022E: Error using adapter to create or execute an Interaction.  
 
Explanation: An exception was thrown while requesting a connection from the Resource Adapter  
 
User Response: Please verify the J2EE Connector (also called the Resource Adapter) configured for use with  
the current bean type is a valid ResourceAdapter. In this case, it is the connection.getInteraction() or  
the interaction itself which is actually failing.
Figure 6. Data Sources
Data Sources

In particular, make sure you are using the correct 390 rsadapter helper class when you define the datasource.

Another thing to try is to turn on trace. For WebSphere Studio, this is simple to do. Open up the server configuration and click on the Trace tab as shown in Figure 7. An interesting package to trace is com.ibm.ws.ejbpersistence. An interesting group to trace is RRA. Among other things, this trace shows the actual SQL strings that are being called through JDBC. In this case, you see the SQL behind your EJBs. This is an interesting activity even when you are not having problems.

Figure 7. Server Trace Options
Server Trace Options

Look in the trace output file to see the extra information generated by the trace. As shown in Figure 7, this is in a file named trace.log. The only remaining question is, where is this file? One nonstandard answer is change the value of the "Trace output file" field shown above. The default location is defined by the ${SERVER_LOG_ROOT}. This is something like [workspace]\.metadata\.plugins\com.ibm.etools.server.core\tmp0\logs\server1\trace.log, where [workspace] is the location of your WebSphere Studio workspace. There is a tmp# directory for each server configuration you create, where # is assigned sequentially for each server. The first one is tmp0.

Question: I'm trying to implement an EJB mapping by root/leaf scheme. I have one EJB that is a subclass of another EJB. The inherited EJB has a primary key which in turn is a foreign key to the parent EJB. I can successfully create an instance of inherited EJB and call its business methods, but when I call its remove() method, I receive the exception below. My WSAD version is 5.1. (submitted by Dmitry)

[9/12/03 11:17:07:687 EDT] 283c283c ExceptionUtil E CNTR0020E: 
Non-application exception occurred while processing method "remove" on bean 
"BeanId(CRM#CRMEJB.jar#Contractor, com.ibm.ejs.container.ProfileKey@a)". 
Exception data: javax.ejb.EJBException: nested exception is: 
com.ibm.ws.ejbpersistence.utilpm.PersistenceManagerException: PMGR6025E: At 
attempted update under optimistic concurrency control failed because the 
bean data has changed in the datastore since this transaction read it. 
Either a predicate field has changed value or the bean itself has been 
removed.

Answer: I tried a little experiment. I used WebSphere Studio 5.1 and DB2 UBD 7.2. I created a Parent and Child EJB shown in Figure 8. These beans are 2.0 EJBs with Container Managed Persistence (CMP) and they have a Container Managed Relationship (CMR).

Figure 8. Parent and Child Entity EJBs
Parent and Child Entity EJBs

Just to speed up my experiment, I created the EJBs and then used a top-down mapping for the DB2 tables. I did create them as a root-leaf implementation. For those reading along, who don't already know, a root-leaf implementation means that I have two tables that represent the two EJBs. The top table is named "Parent" and contains only the columns that correspond to the base class. The second table is called "Child" and contains the data that is unique to the inherited class. In addition, the child table has the same primary key as the parent table. This is what ties the two tables together.

Back to my experiment. Even though I let WebSphere Studio create the schemas for my tables (also known as top-down mapping), I still needed to modify the table schemas. I created a foreign key on the parent table that contains the primary key to the child table. Since I changed the schema, I ended up using a meet-in-the-middle for my new EJBs and the DB2 tables, meaning I had to map these by hand.

My experiment worked. I was able to create and remove either the parent or child EJB. First, I had to update the foreign key on the parent table in my code. The generated EJB code does not help here. Second, I found that the Universal Test Client (UTC), the tool for testing EJBs in WebSphere Studio, was not happy with my parent/child bean relationship. It was giving me class cast exceptions. I had to write a simple session EJB to test the Add and Remove actions of the EJBs. Of course, that's fine because I should not be creating entity EJBs that aren't called by a session EJB. In the end, I tried setting the foreign key attribute to implement a cascading delete, and I was not able to reproduce the error.

None of this helps Dmitriy. However, I looked up the error message PMGR6025E in the WebSphere InfoCenter.

Click to see code listing

PMGR6025E: At attempted update under optimistic concurrency control failed because the bean data has changed  
in the datastore since this transaction read it. Either a predicate field has changed value or the bean itself  
has been removed.  
 
Explanation: Another application probably changed the data in the database while you were using it. Since you  
chose to use optimistic concurrency control (for example, Access Intent = optimisticUpdate), you chose to  
take the chance this might happen to gain other benefits.  
 
User Response: Your application should be written to handle this exception and either retry the update or  
communicate the failure to your end user and let them decide whether to retry the update.

Basically, this means that someone changed the data in your EJB. While that situation can cause this error, I suspect that is not what is happening here. I don't have an exact answer for why you are seeing this error. There are several things you can try. First, go look at the generated SQL for your EJBs. In my experiment, the two EJBs were named "Parent" and "Child". Actually, the full name of Child is com.ibm.test.ejbs.ChildBean.java.

Figure 9. Generated Classes for Child EJB
Generate Classes for Child EJB

Look carefully to find the source code. The package for my EJB is com.ibm.ejbs. I found a package called com.ibm.ejbs.websphere_deploy.DB2UDBNT_72_1. Obviously, this varies with the database product you are using. Within this package, I found a class named ChildBeanFunctionSet_xxxxxxxx.java, where the x's are hexadecimal characters. Double click on this class and you will see the source code that is being used for the Remove in your EJB. In Figure 9, you can also see the file for the parent EJB. One simple experiment is to take the appropriate SQL string from this class and try it out in your favorite SQL utility against the actual database. My personal suspicion is that it will not work. This still does not solve your problem, but making it reproducible is the first step. In this case, an SQL statement might be causing the problem.

A few closing thoughts. If you discover the problem is in the generated SQL, then you might be able to think of a work around. My approach assumes that you are not doing any else that is unusual, like executing your own JDBC code within an EJB. If the database and tables themselves are too complex, then CMP EJBS might not be able to accomplish the task. There are two main schools of thought when CMP EJBs do not fit your need. The first is to use Bean Managed Persistence (BMP). The second approach is to use a well-known pattern of a session EJB that directly invokes JDBC to accomplish the same thing that the Entity CMP EJBs would do. One last thought, you might also want to turn on tracing to get more information. Specifically, trace the RRA group as I explained previously. Turning on this trace is an alternative to looking in the source file as I described above. By tracing the RRA group you will be able to see the SQL that is invoked as a result of the calls to the Entity EJB. Good luck in getting to the root of this error.

Question: Why WebSphere doesn't have EJBs refactoring facilities, such as Renaming, Removing, etc? Do you expect developers not to change their EJBs' name or package through the project? (submitted by Pasha Golshani)

Answer: There are a few subtleties in your question which I will address. In general, I always recommend that you use the perspective that corresponds directly to the artifacts that you are editing. For example, use the J2EE perspective for EJBs, use the Web perspective for Servlets and JSPs, and so on. Your example is one where I would break this rule for convenience. Use the Java perspective for refactoring EJBs when you are modifying the EJBs as Java types. Beware that this only refactors the Java code. You need to update the J2EE artifacts yourself. As you will see, this is really a minor issue and the tool will help.

You can refactor the Java types on your EJB as you can for any other Java class or interface. Before beginning this process, you may want to delete the generated code as I describe in the section below. Here's what I would do to change the name of my EJB implementation class or one of the EJB interfaces:

  1. Use the Java Perspective from the package explorer.
  2. Right-click on the type and select Refactor -> Rename. This does not update your deployment descriptor, ejb-jar.xml. You need to update this file by hand. The task list will show an error for any EJB class or interface that does not exist.
Figure 10. Deleting an EJB
Deleting an EJB

Removing EJBs are another matter. There are several possible meanings for "Removing an EJB." The first meaning is that you want to delete the EJB and everything that comprises the EJB. I am using WebSphere Studio 5.1. From the J2EE perspective, in the J2EE Hierarchy view, right-click on the EJB and select Delete. You are presented with the dialog as shown in Figure 10.

Leave everything checked and this deletes the EJB as defined in the Deployment descriptor, the EJB classes, generated EJB classes, and access beans for this EJB. The next step is to get rid of the EJB definition as part of this application. In other words, you do not want to delete any Java code. From the same dialog box shown above, deselect (uncheck) everything except "Delete Bean Only." This removes the EJB from your deployment descriptor. Another possible step is to delete only the code that WebSphere Studio has generated. To delete the generated code, click the Deselect All button, then check Delete Deployed Code.

A few additional comments. I have given you my favorite way to delete EJB resources, or to refactor EJB code. WebSphere Studio is a powerful tool, built on a powerful platform (Eclipse). There is almost always more than one way to achieve the same results. Do not be afraid to explore. If you have a backup of your code (for example, in an SCM repository, or exported to a jar file), you can feel free to try out some of these other options. For example, you can directly edit the deployment descriptor as an XML file. You can delete generated classes, by shift-clicking, or control-clicking, to select several at once and hitting delete. Just pay attention and understand what you are deleting.

Question: I have been working hard to get this up and running. Can you please help me in finding the solution for the WebGroup not found problem. I have gone through the cause for the problems and found everything to be OK. Here are my environment details: WSAD 5.0, Windows 2000. I have two enterprise application projects:

  1. Test (does not have client and EJB modules)
  2. Royalty (does not have client module)

When I run the index.html file of the "TestWeb" project in the WS Test environment, it works fine. But, when I run the index.html present in the "RoyaltyWeb" project, it gives me the following error. http://localhost:9080/TestWeb/index.html works fine, but http://localhost:9080/RoyaltyWeb/index.html creates the following problem:

Virtual Host or Web Application Not Found 
The web group /RoyaltyWeb/index.html has not been defined 
 
IBM WebSphere Application Server

(submitted by Shaik)

Answer: This message means that the server cannot resolve the http://localhost:9080/RoyaltyWeb/index.html URL for the Royalty Web module. A simple way to double check this is the following. From the server perspective, within the Royal project, right click on index.html, and select Run on Server.... Pay close attention to the URL in the browser. This is the trick I use to have the server tell me that the URL of the item I am trying (sometimes unsuccessfully) to invoke. My guess is that when WebSphere Studio launches a browser, it will have a URL something like: http://localhost:9080/royalty/index.html. The webpage, index.html, should be loaded. The part of the URL I am curious about is "royalty." Obviously, I just made that up for the example here. This is the "Context Root", or your Web application. The older term, that I sometimes still use, is "Root URI." All of your Web resources (html, servlets, JSPs, and so on) should link to each other with an address that is relative to this root.

The context root of a Web project gets set in the wizard that you use to create the Web project. You can change the context root, by right-clicking on the Web project, selecting Properties, and then clicking on Web on the left. In Figure 11, my Web project is using OnlineMall as the context root.

Figure 11. Web Context Root
Web Context Root

Question: I'm using WSAD 5.1 and Windows 2000. When I start WSAD for the first time after PC reboot, WSAD takes 2 minutes to start. But, if I restart just WSAD, then it takes 20 seconds to start. Why? (submitted by DH)

Answer: This is a good question, although I am afraid the answer is not related to WebSphere Studio. I believe what you are seeing is a result of some magic that Windows 2000 is performing. I believe that Windows already has the application image in memory when you restart the application. I tried the same experiment and discovered similar results for Lotus Notes running under Windows XP®. It loads much slower after I reboot than when I just close Notes and then restart it.

For WebSphere Studio, it loads a little faster if you close things before you shutdown. The most important would be to close all open editors and views. There is a preference you can set to close all of the open editor. From the File menu, Workbench -> Editors preference page closes all open editors automatically whenever you exit.

While we are talking about startup, I should mention that depending on what you are doing within WebSphere Studio, you may want to allocate more space to the heap for the Eclipse JVM. Search in the online help for "Running Eclipse" or "-vmargs." Understand that this does not make WebSphere Studio start any faster, but may provide better overall performance.

Another simple thing to do is only use the perspectives you really need. Eclipse does a lazy initialization of resources, and if you do not use a perspective, the corresponding plug-in code is not loaded. Also, beware that once plug-in code gets loaded, it does not get unloaded until Eclipse (WebSphere Studio) is restarted. An extreme measure would be to disable some of the plug-ins that WebSphere Studio is loading. This definitely helps startup time, but you are at the very least crippling WebSphere Studio, and at most, you could break it. For more information about the underlying platform that WebSphere Studio is built upon, I recommend the following resources:

  • The official Website of Eclipse Development team
  • The Java Developer's Guide to Eclipse by Sherry Shavor, Jim D'Anjou, Scott Fairbrother, Dan Kehn, John Kellerman, and Pat McCarthy, one of several books about Eclipse. This one has the distinction of being written by members of the Eclipse team.

Question: I'm trying to create a new port for SSL, for example, 4040, but the WebSphere Test environment does not start. Also, how do you enable SSL in the WebSphere Test environment? Where can I generate the keys for IHS? (submitted by Amira)

Answer: The most obvious answer is that port 4040 is already in use. I took the following steps to duplicate and resolve the problem you describe. I added a secure SSL port to my server configuration in WebSphere Studio as shown in Figure 12.

Figure 12. Server Ports
Server Ports

When I added port 4040 as a secure port (SSL) and started the server, I received this message in the console:

Click to see code listing

[9/27/03 12:48:52:675 EDT] 41404f7e HttpTransport A SRVE0171I: Transport http is listening on port 9,080. 
[9/27/03 12:48:54:177 EDT] 41404f7e HttpTransport A SRVE0171I: Transport https is listening on port 9,443. 
[9/27/03 12:48:54:257 EDT] 41404f7e HttpTransport A SRVE0171I: Transport http is listening on port 9,090. 
[9/27/03 12:48:54:788 EDT] 41404f7e HttpTransport A SRVE0171I: Transport https is listening on port 9,043. 
[9/27/03 12:48:54:868 EDT] 41404f7e TraceNLS      u No message text associated with key  
	Unable.to.get.SSL.context:.in bundle com.ibm.ejs.resources.seriousMessages 
[9/27/03 12:48:54:868 EDT] 41404f7e SSLConfig     E Unable to get SSL context:  
[9/27/03 12:48:54:918 EDT] 41404f7e TraceNLS      u No message text associated with key  
	Unable.to.create.server.socket in bundle com.ibm.ejs.resources.seriousMessages 
[9/27/03 12:48:54:878 EDT] 41404f7e SSLServerSock E Unable to create server socket 
[9/27/03 12:48:54:958 EDT] 41404f7e WebContainer  E SRVE0146E: Failed to Start Transport on host, port 4040.  
	The most likely cause is that the port is already in use. Please ensure that no other applications  
	are using this port and restart the server. com.ibm.ws.webcontainer.exception.TransportException:  
	Failed to start transport https:java.io.IOException: java.lang.NullPointerException: null

Of course, this explains the confusion. I don't have anything listening on port 4040 on my machine. I know, I checked. Let's look again at the ports on the server configuration above. The WebSphere 5.0.x server already has an SSL port defined. In Figure 12, it is port 9443. Don't touch port 9043, this is the SSL port for the administration application that I have configured on my server. The simplest and quickest solution is to modify the 9443 port to 4040 as shown in Figure 13. First, I deleted port 4040 that I defined previously.

Figure 13. Modifying the SSL port from 9443 to 4040
Modifying the SSL port from 9443 to 4040

Now when I start the server, all is well.

Click to see code listing

[9/27/03 12:57:09:830 EDT] 4143d076 ApplicationMg A WSVR0221I: Application started: adminconsole 
[9/27/03 12:57:09:930 EDT] 4143d076 HttpTransport A SRVE0171I: Transport http is listening on port 9,080. 
[9/27/03 12:57:11:512 EDT] 4143d076 HttpTransport A SRVE0171I: Transport https is listening on port 4040. 
[9/27/03 12:57:11:532 EDT] 4143d076 HttpTransport A SRVE0171I: Transport http is listening on port 9,090. 
[9/27/03 12:57:12:023 EDT] 4143d076 HttpTransport A SRVE0171I: Transport https is listening on port 9,043. 
[9/27/03 12:57:12:093 EDT] 4143d076 RMIConnectorC A ADMC0026I: RMI Connector available at port 2809 
[9/27/03 12:57:12:404 EDT] 4143d076 WsServer      A WSVR0001I: Server server1 open for e-business

This is the quickest and easiest to edit the SSL port that is predefined. You cannot create a new SSL port using just the Server Properties editor. For complete control over the configuration, use the Administration Console. Most of the time when I am working in WebSphere Studio, I don't use a Web server, I just browse to the port on the Application Server. As you can see from the figures above, this is usually port 9080. This also works for an SSL connection. My browser happily and securely connects on port 4040 using this example.

To work with certificates for the IBM HTTP Server (IHS), use the IKMAN program. For detailed information, see the HTTP Server InfoCenter and search for "IKMAN" or "SSL."

Question: I am trying to implement LDAP security in WSAD 5.0 to test our J2EE application. Do you know of any documentation to handle this? We currently are using IBM Secureway 3.2.2 and we are in the process of upgrading to IBM IDS V5.1 in WAS. (submitted by TM)

Answer: I've been asked this same question before, so I think it might make a good article for the WebSphere Developer Domain team. There is an excellent article that describes setting up custom security for WebSphere Application Server that is used by WebSphere Studio, Testing J2EE Security Applications Using a Custom Registry in WebSphere Studio V5.

The first part of this article describes how to set up and use the Console Application within WebSphere Studio. This is useful to know as I have indicated previously in this article. With WebSphere Studio V5, there is a complete version of a built-in base WebSphere Application Server. In fact, it's even better than that, you get WebSphere Application Server V5 and V4.0. My answer here relates to WebSphere Studio 5.0 and WebSphere Application Server 5.0.

First, enable the Administration Console as shown in Figure 14.

Figure 14. Enabling the Admin Console
Enabling the Admin Console
  1. Restart the server for the Admin Application to be started within your server.
  2. When the server is restarted, right-click on the server in the servers view and select Run administrative console. This loads a browser that points to the URL of the Admin Console. This address is http://localhost:9090/admin.
  3. Enter your user ID at the console. You do not have a security setup yet so any user ID is fine.
  4. On the left side, expand Security, Authentication Mechanisms, and User Registries as shown in Figure 15.
    Figure 15. Admin Console
    Admin Console
  5. The most complicated part is setting up LDAP as your user registry. Click on the LDAP link under User Registries.
  6. Enter the information for your LDAP registry as shown in Figure 16.
    Figure 16. LDAP User Registry
    LDAP User Registry

    The Server User ID and Server Password are the LDAP identity that your server uses when it is running. I always think of this as "WebSphere's Identity." Your directory type is IBM Directory Server. Keep in mind that selecting your directory type simplifies the configuration process when you are using the "out of the box" schema for your LDAP server. For schemas that do not match the default, edit the Advanced LDAP Settings. (The link is not shown on the figure, it is at the bottom of this screen.) Obviously, you will need to provide the host and port for the LDAP server. The Base Distinguished Name (DN) tells WebSphere where to start searching in your LDAP server. In many cases, the Bind DN and password are not required. This is only required if your LDAP server has been setup with security that requires authentication. This authentication searches the registry for information that WebSphere Application Server requests (groups, users, and so on). It is recommended that "Ignore Case" is selected for the IBM Directory Server. You can find more information about specific LDAP server configurations in the WebSphere Info Center and search for "IBM Directory Server" or "LDAP."

  7. After entering all the information, click Apply to save this screen. The Application Server authenticates the user ID and password you entered for WebSphere against your LDAP server. You know you've gotten that part right if you don not see any error messages.
  8. Save the Server Configuration.
  9. Now that you have configured the Server to use LDAP as the registry, you need to enable security. Still in the console, click on the Global Security link on the left.
    Figure 17. Global Security
    Global Security
  10. Click on Enabled and change the Active User Registry to LDAP. Note that the Enforce Java 2 Security becomes enabled when you enabled the global security. If you are not using Java 2 Security, you may want to disable it. As the note on the right on the console states, "If Java 2 Security is enabled and the application policy file is not set up correctly, the application may fail to run." Sounds like a warning to me.
  11. Apply this change and save your server configuration.
  12. Restart the server for these settings to take effect. The next time you use the Application Console, you need to authenticate with a valid LDAP identity.

Just a couple of closing comments. I have given you just a quick guide to get you started. There is much more to configure and to understand. I have not scratched the surface. There are Lightweight Third Party Authentication setting (LTPA), custom LDAP setting, and Secure Socket Layer (SSL) settings specifically for LDAP. Keep reading that InfoCenter.

Question: I'm using datasources in MessageDrivenBeans. I get following error when I try to use it. I'm using WebSphere 5.0.2.

[9/15/03 9:06:16:603 PDT] 481322cb TransactionIm E WTRN0062E: An illegal attempt to use multiple 
	resources that have only one-phase capability has occurred within a global transaction. 
[9/15/03 9:06:16:884 PDT] 481322cb LocalTransact E J2CA0030E: Method enlist caught  
	java.lang.IllegalStateException 
at com.ibm.ejs.jts.jta.TransactionImpl.enlistResource(TransactionImpl.java:567) 
at com.ibm.ejs.jts.jta.JTSXA.enlistResource(JTSXA.java:1061) 
at com.ibm.ejs.jts.jta.JTSXA.enlistOnePhase(JTSXA.java:1038) 
at com.ibm.ejs.j2c.LocalTransactionWrapper.enlist(LocalTransactionWrapper.java:507) 
at com.ibm.ejs.j2c.ConnectionEventListener.interactionPending(ConnectionEventListener.java:743) 
at com.ibm.ws.rsadapter.spi.WSRdbManagedConnectionImpl.processInteractionPendingEvent 
	(WSRdbManagedConnectionImpl.java:1299)

It seems to me that WebSphere is trying to use Message Connection and JDBC connection as part of the same transaction. Is that how it should be? Or, is there anything specific I have to do in the deployment descriptors? Below is a snippet of ejb-jar.xml:

<message-driven id="MessageDriven_1063383809274"> 
<ejb-name>ErrorLogMessageBean</ejb-name> 
<ejb-class>com.mindfabric.logging.error.ErrorLogMessageBean</ejb-class> 
<transaction-type>Container</transaction-type> 
<message-driven-destination id="MessageDrivenDestination_1063383973617"> 
<destination-type>javax.jms.Topic</destination-type> 
<subscription-durability>NonDurable</subscription-durability> 
</message-driven-destination> 
<resource-ref id="ResourceRef_1063383973633"> 
<res-ref-name>jdbc/centralDB</res-ref-name> 
<res-type>javax.sql.DataSource</res-type> 
<res-auth>Container</res-auth> 
<res-sharing-scope>Shareable</res-sharing-scope> 
</resource-ref> 
</message-driven>

(submitted by BC)

Answer: You are absolutely correct. You are invoking a transactional resource (JDBC resource) from within the transactional context of the Message Driven Bean (MDB). It is difficult to know what the right answer is until we determine what you want to happen. In most cases, I want the JDBC call to be part of the same transaction as the delivery of the message to the MDB. If you are calling DB2, then the answer might just be to use the XA driver. In my version of WebSphere Studio, the JDBC driver defaults to the COM.ibm.db2.jdbc.DB2ConnectionPoolDataSource as the implementation class. That's fine for simple stuff, but it doesn't support full two phase commit. I expect to see a similar message to the one you've listed above. If I really want the full two phase commit, I can use the COM.ibm.db2.jdbc.DB2XADataSource implementation class.

The other possibility is that you don't care about the transaction of the JDBC call or the method invocation on the Message Driven Bean. In this approach, mark the method on the MDB as NotSupported. Remember this assumes that you don't want the message delivered to the bean within a transaction.

About Meet the Experts

Meet the Experts is a monthly feature on WSDD. We give you access to the best minds in IBM WebSphere, product experts and executives who are waiting to answer your questions. You submit the questions, and we post the answers to the most popular questions.

Resources

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into WebSphere on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere
ArticleID=14190
ArticleTitle=Meet the experts: Matthew Oberlin on WebSphere Studio Application Developer
publish-date=09182003