... until the collector arrives ...

This "blog" is really just a scratchpad of mine. There is not much of general interest here. Most of the content is scribbled down "live" as I discover things I want to remember. I rarely go back to correct mistakes in older entries. You have been warned :)

2006-01-27

Java Coding Conventions

There was some internal debate about Java coding conventions.  For reference, here are the conventions of some well-known groups or projects:

Sun http://java.sun.com/docs/codeconv/html/CodeConvTOC.doc.html
Eclipse http://dev.eclipse.org/conventions.html
Apache Jakarta http://jakarta.apache.org/cactus/participating/coding_conventions.html
ANT http://ant.apache.org/ant_task_guidelines.html
JBoss http://docs.jboss.org/process-guide/en/html/coding.html

 

Ant 1.6

I was using a copy task to copy a particular file using <fileset file="${bea-xbean-jar}"/>, but the file consistently failed to be copied.  The problem was that the variable bea-xbean-jar was defined in an external build.properties file, but the line contained a trailing space.

2006-01-25

Axis

Using Apache Axis, if you invoke a web service and pass the wrong number of arguments, you will see the error 'no such operation', which can be misleading.

2006-01-24

WebLogic 9.1 Web Services

On the topic of null pointer exceptions, I tried to create a JWS web service that accepted a POJO argument that had a SOAPElement property.  It compiled and deployed fine, but when I invoked the web service, I got the dreaded NPE:

java.lang.NullPointerException at test.TestServiceImpl.operation1(TestServiceImpl.java:17) at
        sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
        sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at
        sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at
        java.lang.reflect.Method.invoke(Method.java:585) at
        weblogic.wsee.component.pojo.JavaClassComponent.invoke(JavaClassComponent.java:91) at
        weblogic.wsee.ws.dispatch.server.ComponentHandler.handleRequest(ComponentHandler.java:68) at
        weblogic.wsee.handler.HandlerIterator.handleRequest(HandlerIterator.java:127) at
        weblogic.wsee.ws.dispatch.server.ServerDispatcher.dispatch(ServerDispatcher.java:84) at
        weblogic.wsee.ws.WsSkel.invoke(WsSkel.java:60) at
        weblogic.wsee.server.servlet.SoapProcessor.handlePost(SoapProcessor.java:66) at
        weblogic.wsee.server.servlet.SoapProcessor.process(SoapProcessor.java:44) at
        weblogic.wsee.server.servlet.BaseWSServlet$AuthorizedInvoke.run(BaseWSServlet.java:124) at
        weblogic.wsee.server.servlet.BaseWSServlet.service(BaseWSServlet.java:53) at
        javax.servlet.http.HttpServlet.service(HttpServlet.java:856)

If I declare the service with a SOAPElement as a direct parameter, it works as advertised.

XFire

I struggled with the sample web service provided with the XFire distribution.  The problem was that I placed the XFire services configuration XML in the WAR's META-INF directory instead of within classes/META-INF.  Incidentally, I discovered that in a servlet context getClass().getClassLoader().getResource() does not search the root context directory for resources -- it only searches the classes and lib subdirectories.  To get a resource from the root, you must use getServletContext().getResource().  After this short detour, the XFire service worked.

I was unable to get the XFire test framework run the service.  It throws a null pointer exception:

java.lang.NullPointerException
	at org.codehaus.xfire.handler.LocateBindingHandler.invoke(LocateBindingHandler.java:41)
	at org.codehaus.xfire.handler.HandlerPipeline.invoke(HandlerPipeline.java:97)
	at org.codehaus.xfire.transport.DefaultEndpoint.onReceive(DefaultEndpoint.java:57)
	at org.codehaus.xfire.transport.AbstractChannel.receive(AbstractChannel.java:38)
	at org.codehaus.xfire.test.AbstractXFireTest.invokeService(AbstractXFireTest.java:116)
	at org.codehaus.xfire.test.AbstractXFireTest.invokeService(AbstractXFireTest.java:91)
	at mm_test.BookService_Test.testBookService(BookService_Test.java:18)

WebLogic JWSC Ant Task

As I noted in a previous entry, the WebLogic JWSC task will not run unless the BEA JARs are in the classpath of the JVM that his hosting Ant.  Here is a way to make that happen in the context of an Ant script:

<path id="bea-classpath">
  <pathelement location="${bea-wls-home}/server/lib/weblogic.jar"/>
  <pathelement location="${bea-wls-home}/server/lib/webservices.jar"/>
</path>

<taskdef name="jwsc"
  classname="weblogic.wsee.tools.anttasks.JwscTask"
  classpathref="bea-classpath"
  />

<target name="~jwsc">
  <delete dir="build"/>
  <mkdir dir="build"/>
  <jwsc
    srcdir="src"
    destdir="build"
    classpathref="bea-classpath"
    verbose="true"
    >
    <jws file="test/TestServiceImpl.java"/>
  </jwsc>
</target>

<target name="jwsc">
  <java classname="org.apache.tools.ant.launch.Launcher" fork="true">
    <classpath>
      <pathelement path="${java.class.path}"/>
      <path refid="bea-classpath"/>
    </classpath>
    <sysproperty key="ant.home" value="${ant.home}"/>
    <arg value="-buildfile"/>
    <arg value="${ant.file}"/>
    <arg value="~jwsc"/>
  </java>
</target>

2006-01-23

WebLogic 9.1 JWS vs. XMLBeans

I tried to create a web service that accepts an XMLBean as its sole input parameter and produces an XMLBean as its return value.  JWSC was able to compile it, but when I invoked the service I got a SOAP fault reporting the stack trace:

com.bea.xml.XmlRuntimeException: java.lang.InstantiationException: com.bea.xml.XmlObject
        at com.bea.staxb.runtime.internal.ClassLoadingUtils.newInstance(ClassLoadingUtils.java:137)
        at com.bea.staxb.runtime.internal.ByNameRuntimeBindingType.createIntermediary(ByNameRuntimeBindingType.java:196)
        at com.bea.staxb.runtime.internal.AttributeUnmarshaller.unmarshal(AttributeUnmarshaller.java:36)

I guess the deserializer is looking for a no-arg constructor for XmlObject.  As of WLS 9.0, there is no longer a way to register a custom deserializer to overcome the absence of a no-arg constructor/bean pattern.

It would appear that others are having similar problems.

WebLogic 9.1 JWSC Ant Task

I tried to follow an example from the WLS9.1 web services documentation that uses the JWSC Ant task.  I got the error message:

Deployment descriptor: tempdir\_9tdo9x\web.xml does not exist.

I found a message in the BEA forums that suggested using BEA's setDomainEnv command before running the Ant task.  This worked, but complicates using a stock "headless" Ant build (e.g. running within Eclipse or CruiseControl).  I had found a similar bug in WLS8.1's source2wsdd Ant task (the other WLS8.1 Ant tasks had no such dependencies).

I ran Ant with -debug and saw this:

Deployment descriptor: C:\DOCUME~1\MM\LOCALS~1\Temp\_9tdo9x\web.xml does not exist.
 at org.apache.tools.ant.taskdefs.War.setWebxml(War.java:84)
 at weblogic.wsee.tools.anttasks.JwscTask.jar(JwscTask.java:397)
 at weblogic.wsee.tools.anttasks.JwscTask.pkg(JwscTask.java:331)
 at weblogic.wsee.tools.anttasks.JwscTask.execute(JwscTask.java:166)

 the option explode="true" on the jws subelement of the jwsc task, then the process seems to proceed a little bit further, but then dies for a completely different reason:

java.lang.AssertionError: java.lang.ClassNotFoundException: weblogic.j2ee.descriptor.ApplicationBeanImpl
 at weblogic.descriptor.internal.DescriptorImpl.createRootBean(DescriptorImpl.java:357)
 at weblogic.descriptor.DescriptorManager.createDescriptorRoot(DescriptorManager.java:328)
 at weblogic.wsee.tools.jws.build.EarFile.getApplicationBean(EarFile.java:127)
 at weblogic.wsee.tools.jws.build.EarFile.addWebModule(EarFile.java:61)
 at weblogic.wsee.tools.anttasks.JwscTask.addToEar(JwscTask.java:230)
 at weblogic.wsee.tools.anttasks.JwscTask.execute(JwscTask.java:167)

That last one looks like a typical Ant classloader problem since the named class actually *does* exist in weblogic.jar.  I looked at the code for DescriptorImpl.createRootBean() and found that it was hard-coded to use the thread's class loader (instead of using its own class loader).  In an Ant context, the implications of this are complex, resulting in the exhibited failure.

[I later found a workaround.]

WebLogic vs. Web Services

I am still having troubles writing a web service for use in esi.execute.  The requirements, and problems, are recounted in the following table.

Requirement WLS 8.1 WLS 9.1
deployable on WLS ok ok
can be built using Ant ok JWSC task has issues (see below)
primary web service defined as a Java interface finicky, but possible ok
supports XMLBeans as parameters/result (for compatibility with the ALDSP 2.0 stack) yes, through custom serializers The docs suggest that XMLBeans can be used, but are deprecated.  However, I can't get it to work (see below).  The docs also mention using a generic SOAPElement for untyped data, but this would require two in-memory copies of the XML document (i.e. the SOAPElement implementations, and our own implementation in XMLBeans or whatever).

WLS 9.1 no longer supports custom serializers.

supports arguments that are partly strongly typed and partly untyped (i.e. "raw XML")
supports streaming (a "nice-to-have") yes, through custom serializers no
supports Java 1.5 no yes

WebLogic JARs vs Eclipse

Whenever I am working in an Eclipse project that references one or more of the WebLogic JARs, the IDE performance is extremely poor.  The IDEA seems to be consuming nearly 50% of the CPU in the background doing something -- scanning the huge weblogic.jar perhaps?  Code completion is especially affected.

2006-01-19

BEA WebLogic 8.1

The best place to supplement the CLASSPATH used by the WebLogic server is to edit %WLS_HOME%/common/bin/commEnv.cmd (or .sh on Unix) -- at least if you want the change to apply to all WebLogic domains.

I found a note about running XFire on WebLogic 8.1.  It says that XFire requires a newer version of the standard java QName class, and that this can only be accomplished by adding that class to the front of WebLogic's classpath.  I wonder if this is the same problem that we were hitting with JDK 1.5?

Following this hint, I determined inspected the serialization versions of the various versions of the class javax.xml.namespace.QName:

  • XFire's proposed "fix" version: -9120448754896609940L
  • BEA's version in WebLogic.jar: -9120448754896609940L
  • Sun JDK 1.5: 4418622981026545151L

I was surprised to see the XFire and BEA versions had the same version.  However, using javap on the three files revealed that the XFire and 1.5 versions had a new method, getPrefix().

So... I created a JAR with just the 1.5 version and threw it in JRockITs jre/lib/endorsed directory.  The WebLogic server failed to start up with an UnsupportedClassVersionError for version 49.0.  Next, I got the 1.5 source for QName and compiled it with a 1.4 compiler, and then put this class in a jar in JRockITs endorsed directory.  The server launched, and I was able to use a Java 1.5 client to access an AquaLogic DSP service.  Presumably, XFire would work as well, but I haven't tried that yet.

BEA WebLogic

I tried again to find an idiomatic way to create web services for BEA that:

  1. can be developed in Eclipse without the use of BEA's workshop
  2. can be built by ANT
  3. favour expression of interfaces in Java over WSDL or XSD
  4. preserve the use of SDO and XmlBeans
  5. use the same classes on the client and server side
  6. allow portions of the SOAP requests or replies to be untyped XML

So far, 1, 2, 3, 4, 5, and 6 seem in reach, but 7 remains elusive. 7 can be achieved by using BEA's proprietary .JWS format, but then some of the other goals are missed (especially 1).

Most of the time today was spent wrestling with, and finally identifying an apparent bug in WLS. See the BEA newsgroup posting:

http://forums.bea.com/bea/thread.jspa?threadID=200079921

Other BEA findings...

As of 9.1, BEA deprecates the use of XMLBeans in Web Services: http://e-docs.bea.com/wls/docs91/notes/new.html.  Does that mean you can't use XMLBeans at all, or just that you shouldn't declare a type as a generic XmlObject?

How do you configure and recover initialization parameters for web services?

Whether generating a service from WSDL (using WSDL2Service) or from Java (using SERVICEGEN), the deployed WSDL does not generate unique SOAPActions for each operation. In fact, they are all blank. As a result, a client is not able to invoke any operation other than the first. Note that even when WSDL2Service is given a WSDL that *does* correctly specify SOAPActions, the deployed service still uses blank actions.

If you write a web service using BEA's proprietary JWS format, then correct SOAPActions are generated.

There are some BEA forum posts about this::

When using SERVICEGEN, make sure that the target EAR file does not exist prior to running the task. Otherwise, the task will update the existing EAR file, and may not actually replace the WebService class. In my case, I had added some methods, but since the class file was not updated, the methods did not appear. I got the error message:

 at weblogic.webservice.server.WebServiceFactory.registerOperation(Lweblogic.management.descriptors.webservice.OperationMBean;Lweblogic.webservice.Port;Lweblogic.webservice.InvocationHandler;Ljava.util.Map;Lweblogic.xml.schema.binding.TypeMapping;Ljava.lang.String;Ljava.util.HashSet;ZV(WebServiceFactory.java:869)

WebLogic 8.1 JWS Files

Having discovered that there is a bug in SERVICEGEN where generated web service operations have blank SOAPActions, and that JWS files generated in the workshop do not exhibit this problem, I decided to see how the latter were being annotated.  First I poked around in the generated EAR file looking for some kind of deployment descriptor.  Nothing.  In fact, all I could find was a class file, sitting in the .workshop directory in the JAR file (not even in WEB-INF!).  I suspected that BEA was generating non-standard class properties in the class file, so I wrote a short program using BCEL to dump the properties.  Lo and behold!  There is non-standard property called com.bea.wlw.annotation.v2, that contains a WSDL fragment, some schema, and a bunch of binary (serialized?) stuff.  The upshot is that only the BEA compiler can be used to generate these classes (or perhaps only the WebLogic workshop itself).

2006-01-18

JScience

I found JScience, a set of Java libraries with functionality related to linear algebra.  Of interest are the facilities for units of measurement, a monetary data type, and credible rational number types to replace Java's hokey BigInteger and BigDecimal types.

Trac

Wing pointed us to Trac, and open-source combined wiki and issue-tracking system with Subversion integration.

2006-01-16

XFire

I found XFire, yet-another SOAP engine that claims both performance and simplicity.

JIRA

In JIRA, an administrator can edit the work logs of an issue by hitting a URL like this:

http://jira-context/secure/admin/editworklog.jsp

e.g.

http://mm1:8080/secure/admin/editworklog.jsp

2006-01-12

BEA WebLogic ActiveDirectory Configuration

In the console:

  1. select the default realm in the Security/Realms node.
  2. select the Providers/Authentication node
  3. configure a new Active Directory Authenticator
  4. set Host to the AD server (e.g. dc.mm.local)
  5. set Principal to the DN of a user account that can query the LDAP server (e.g. CN=Service Account,OU=Service Accounts,OU=mm,DC=mm,DC=local)
  6. set Credential to the password for the user account
  7. switch to the Users tab
  8. set User Object Class to user
  9. set User Name Attribute to sAMAccountName
  10. leave User Dynamic Group DN Attribute blank
  11. set User Base DN to the root of the user tree (e.g. DC=mm,DC=local)
  12. set User From Name Filter to (&(sAMAccountName=%u)(objectclass=user))
  13. switch to the Groups tab
  14. set Group Base DN to the base of the group tree (e.g. DC=mm,DC=local)
  15. set Static Group Object Class to group
  16. set Static Group Name Attribute to cn
  17. switch to the Details tab
  18. check Use Token Groups for Group Membership Lookup
  19. Restart the server.
  20. Verify that these changes work by browsing the Users and Groups nodes under the realm.

Many of these settings can be figured out by browsing the AD LDAP tree using an LDAP browser.

BEA WebLogic

WebLogic 8.1 claims to support JAX-RPC 1.0, but I found that the implementation of the ServiceLifeCycle interface always passed null as the context, so you cannot recover the servlet context.  Later investigation found that BEA's documentation noted this deficiency.  I need the servlet context to recover the UserPrincipal object.

The WebLogic 9.0 documentation is evasive on the topic.  The documentation emphasizes the new .JWS functionality which is not covered by any standard.  It claims the JAX-RPC 1.1 but all the examples only deal with client side code.  Indeed, all methods of generating web services other than through .JWS files are deprecated.  The documentation also claims that Enterprise Web Services 1.0 is supported but, again, none of the examples or tools seem to agree with that statement.

Eclipse Plug-in Development

This morning when I opened my Eclipse workspace, one of my RCP projects had problems with its build paths.  On the 'libraries' property page, the entry that is normally called 'Plug-in Dependencies' was labelled 'org.eclipse.pde.core.requiredPlugins (unbound)' and the container was empty.  After much experimenting, I discovered I could fix the problem by closing and re-opening the project, followed by a 'clean'.

My workbench showed errors on start-up:

Error 2006-01-12 08:07:48.184 An internal error occurred during: "Initializing Java tooling".
java.lang.NullPointerException
at org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify(BasicNotifierImpl.java:229)
at org.eclipse.wst.common.internal.emf.resource.TranslatorResourceImpl.setID(TranslatorResourceImpl.java:310)
...[snip]...

Error 2006-01-12 08:07:48.169 Problems occurred when invoking code from plug-in: "org.eclipse.core.resources".
java.lang.ArrayIndexOutOfBoundsException: 4
at org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify(BasicNotifierImpl.java:229)
at org.eclipse.emf.common.notify.impl.NotificationImpl.dispatch(NotificationImpl.java:931)
at org.eclipse.wst.common.componentcore.internal.impl.ComponentResourceImpl.setComponent(ComponentResourceImpl.java:216)
at org.eclipse.wst.common.componentcore.internal.impl.ResourceTreeNode.findMatchingVirtualPathsSet(ResourceTreeNode.java:210)
...[snip]...

Warning 2006-01-12 08:07:39.347 A workspace crash was detected. The previous session did not exit normally.

although as far as I can remember the previous session did exit normally.

2006-01-11

Eclipse JST Web Services

I tried to use the Eclipse JST wizard to generate a web service.  I kept getting the error:

java.lang.NoClassDefFoundError: javax/activation/DataSource

whenever during WSDL generation (or parsing).  A Google search revealed that this is a very common problem -- see, for example, Eclipse Bugzilla 104993.  I couldn't find a solution on the Web, but I discovered that if I added activation.jar from the JavaBean Activation Framework to my project build path, everything worked.  I had to exit and re-enter Eclipse for the change to work.  Also, I found that after I had run the wizard successfully once, it worked forever more (i.e. without having to add activation.jar to a project, and in following Eclipse sessions).  Something is being cached somewhere.

2006-01-04

Wink

I found some nice screencasting freeware called Wink.  It creates Flash, HTML, or PDF presentations from screen captures.

2006-01-02

Eclipse RCP vs RCP SDK

If you use the Eclipse RCP binary instead of the RCP SDK, there are various problems in the development environment.  Many of the plug-in property pages were truncated, displaying only the top few widgets (and cutting off the last widget shown).  Also, the extensions panel was not showing the various extension attribute types under the 'New' context menu (e.g. category, view, and stickyView were not available for extensions of type org.eclipse.ui.views).

Blog Archive