Eben Hewitt on Java

Eben Hewitt writes about Java, Service-Oriented Architecture, and general enterprise software development practices.

Using SOAP Faults and Exceptions in Java JAX-WS Web Services

Using SOAP Faults and Exceptions in Java JAX-WS Web Services

Pick up a copy of Java SOA Cookbook by Eben Hewitt for more stuff like this.

This article shows you how to avoid this error: javax.xml.ws.soap.SOAPFaultException: java.lang.NoSuchMethodException

This article shows you how to create proper throws clauses in your Java web services, and how to write JUnit 4.4 unit tests to handle the exceptions that you get, and mapping semantics with Java exceptions and SOAP Faults. It also shows you how to use the @WebFault annotation.

If you see a stack trace like this in your Java web service client, the answer is below:

javax.xml.ws.soap.SOAPFaultException: java.lang.NoSuchMethodException: com.example.MyExceptionBean.setMessage(java.lang.String)
        at com.sun.xml.internal.ws.fault.SOAP11Fault.getProtocolException(SOAP11Fault.java:171)
        at com.sun.xml.internal.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:94)
        at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:240)
        at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:210)
        at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:103)
        at $Proxy33.verify(Unknown Source)

I.
Let's start with a regular Java class with an operation that throws an exception, like this:

public class CheckVerify {
    public MessageResponseType verify(CheckType check)
        throws MyException { ... }
}

Because annotations are so easy in JAX-WS, I would expect that I could turn such a class into a Web Service using annotations, have the deployment tool run wsgen and create the web service artifacts (WSDL and XML Schema) for me, which it would. I would expect that Java would handle the exception for me like it does everything else: it turns the regular method into an 'operation' in the WSDL--it should also turn the 'throws MyException' into a '<soap:fault name="MyException" use="literal"/>' in the WSDL too. It does.

So what's the problem?

The problem is that while this web service will deploy, this doesn't actually work for a generated Java client of that web service. You need to know a little more, and make use of an additional annotation and something called a fault bean. This article shows you how.

II.

When implementing a web service using Java and JAX-WS, you might want to code in a natural style that allows you to throw an exception from your service operation, and have the runtime translate that into a SOAP fault that is received on the client.

You can code exceptions in JAX-WS, but the documentation on the web for this is practically non-existent, which is strange because it's such a common thing for Java programmers to want to do. Sometimes you have no choice but to deal with a checked exception that an underlying library throws (IOException is common). We need to know how to deal with this.

Say we have the following web service--the annotated version of the class we started with above. It's called CheckVerify and it defines a single operation that makes sure that a check writing customer is not known to the bad check writer database:

@WebService(
    serviceName="CheckVerifyService",
    portName="CheckVerify",
    targetNamespace="
http://www.example.com")
public class CheckVerify {
    @WebMethod(operationName="verify")
    public @WebResult(name="checkVerifyResponse",
            partName="checkVerifyResponse",
            targetNamespace="
http://www.example.com")
            MessageResponseType
    verify(
    @WebParam(name="check",
        partName="check",
        targetNamespace="
http://www.example.com")
        CheckType check)
        throws CheckVerifyFault {
    //...
 }
}

This operation throws a CheckVerifyFault. Say that our implementation of the verify method actually calls a second, remote web service that uses HTTPS to validate the check, or goes to a database using JDBC. There might be checked Java exceptions that we want to translate into a SOAP Fault to use to return to the client.

Here's the portType snippet of the WSDL that results from these annotations:

<portType name="CheckVerify">
<operation name="verify">
<input message="tns:verify" />
<output message="tns:verifyResponse" />
<fault message="tns:MyException" name="MyException" />
</operation>
</portType>


While the above code will deploy to a container such as WebLogic, it won't have the desired result on the client.

First of all, JAX-WS will create an exception class for us, which is nice. But the exception class will be called MyException_Exception on the client side. Doing what we want is a more complicated and obscure part of the JAX-WS model, and using exceptions is not quite as easy as other things in JAX-WS.

If we run wsimport before our automated test, then compile the generated code and run the test, we'll see what effect this code has on the client view. And we'll have a good basis for undersanding the client side of this.

First we know that we want to change the name of the generated exception to something more friendly. So let's use bindings file to customize the generated code. You can read more about this in Java SOA Cookbook, but if you're using Maven to run the build that executes your wsimport, you can put a file called bindings.xml in the src/jaxws folder. Give that file the following contents:

<?xml version="1.0" encoding="UTF-8"?>
<bindings
    xmlns="
http://java.sun.com/xml/ns/jaxws"
    xmlns:wsdl="
http://schemas.xmlsoap.org/wsdl/">
    <bindings node="wsdl:definitions/wsdl:portType[@name='CheckVerify']/wsdl:operation[@name='verify']/wsdl:fault[@name='MyException']">
        <class name="MyFault">
            <javadoc>Exception generated during any operation with the service.</javadoc>
        </class>
    </bindings>
</bindings>

This uses XPath to find the node in the generated WSDL that matches the fault with the name of "MyException" and indicates that the generated class should be named MyFault.

JAX-WS will create two classes now: MyFault, which is the JAXB customization re-name of the MyException class, and a class called MyException. That class will be a bean that holds a message.

The generated MyFault class on the client looks like this:

@WebFault(name = "MyException", targetNamespace = "http://www.example.com")
public class MyFault extends Exception {

    /**
     * Java type that goes as soapenv:Fault detail element.
     */
    private MyException faultInfo;


    public MyFault(String message, MyException faultInfo) {
        super(message);
        this.faultInfo = faultInfo;
    }

    public MyFault(String message, MyException faultInfo, Throwable cause) {
        super(message, cause);
        this.faultInfo = faultInfo;
    }

    public MyException getFaultInfo() {
        return faultInfo;
    }

}

The class is annotated with @WebFault, but indicates in its 'name' attribute that it is called MyException, which is the bean class (shown below) that we were renaming in our JAXB XML customization file.

So this is where things start getting weird. Notice that a MyFault constructor takes a MyException type. There is not a no-arg constructor in MyFault. The faultInfo (of type MyException) is expected to contain the SOAP Fault detail information. That is, there is a class (here, MyException, that holds the data element value of the <detail> element child of the <soap:fault> in the underlying SOAP envelope--the exception class is not doing that work for us.

So the first thing to understand is that MyException is not an exception type at all, but a regular bean that acts as a holder for the SOAP Fault information, to ensure it complies with that contract (because a SOAP Fault is not the same as a Java checked exception; checked exceptions don't exist in many languages). Put another way, even if you coded your exception to include a message String along with a getter and setter for it that could hold this info, JAX-WS doesn't know about it, so you need to define it explicitly.

So here is that generated 'exception' class, which is really not an exception at all, and rather a bean that your MyFault class (which actually IS the client-side exception class) accepts.

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "MyException", propOrder = {
    "message"
})
public class MyException {

    protected String message;

    public String getMessage() {
        return message;
    }

    public void setMessage(String value) {
        this.message = value;
    }
} //comments deleted

Because the WSDL is valid and JAX-WS generated these classes for you, you might think that everything would work at this point. But it won't. Let's write the naive unit test we expect would work around this code on the client.

public class CheckVerifyServiceTest {

    public static final Logger LOGGER = Logger.getLogger(CheckVerifyServiceTest.class);

    private static final String WSDL_URL_KEY = "checkVerify.wsdl.url";

    private static final QName QNAME = new QName(
            "
http://www.example.com", "CheckVerifyService");

    private static CheckVerify checkVerify;

    private static final String TODAY;
    @BeforeClass
    public static void setup() throws Exception {
        LOGGER.debug("Attempting to initiate service...");
        String wsdl = System.getProperty(WSDL_URL_KEY);
       
        LOGGER.debug("Using WSDL: " + wsdl);
        final URL wsdlUrl = new URL(wsdl);

        final CheckVerifyService service = new CheckVerifyService(wsdlUrl, QNAME);
       
        checkVerify = service.getCheckVerify();
               
        if (checkVerify != null) {
            LOGGER.debug("Found service stub.");
        } else {
            fail();
        }
    }

    @Test
    public void testMe() {
        LOGGER.debug("Executing...");

        CheckType check = new CheckType();
        //....

        MessageResponseType response = null;
        try {

            response = checkVerify.verify(check);

            LOGGER.debug("Completed Exception response.");

        } catch (MyFault ex) {
            LOGGER.error("Error class: " + ex.getClass().getName());
            LOGGER.error("Caught error. Message: " + ex.getMessage());

            assertTrue(true);
        }
    }
}

In our @BeforeClass annotated method we use the generated service stub to get the port type for the service, and use that in our tests.

In the @Test method we invoke the verify method that throws the MyException exception (which we renamed to MyFault using JAXB customizations). So we put a try/catch around it and we should be able to expect that if we do something to make the method throw a fault/exception, that it would be caught here and our assertion would pass and everything would be fine, right? Wrong. The above code doesn't work.

NOTE: The proper way to positively test that your method throws an exception when it is supposed to in JUnit is with the @Test(expected=MyFault.class) annoation attribute. We want to look at the details here, so this is for illustration.

Here's what happens when you run the above test is that the test compiles but results in an ERROR (not a regular test failure):

testMe(com.dte.soa.checks.ws.CheckVerifyServiceTest)  Time elapsed: 0.094 sec  <<< ERROR!
javax.xml.ws.soap.SOAPFaultException: java.lang.NoSuchMethodException: com.dte.soa.checks.ws.jaxws.MyExceptionBean.setMessage(java.lang.String)
        at com.sun.xml.internal.ws.fault.SOAP11Fault.getProtocolException(SOAP11Fault.java:171)
        at com.sun.xml.internal.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:94)
        at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:240)
        at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:210)
        at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:103)
        at $Proxy33.verify(Unknown Source)


The problematic thing here is this line:

javax.xml.ws.soap.SOAPFaultException: java.lang.NoSuchMethodException: com.example.MyExceptionBean.setMessage(java.lang.String)
      
The problem appears to be that there is no method called setMessage in the MyExceptionBean class. This seems like a bug in JAX-WS, because we didn't write any class called MyExceptionBean, and it's not listed in our classes under the Generated Sources, so how could we possibly fix this?

The answer is to do this on the service side:
1. Write a class that extends Exception.
2. Annotate it with @WebFault and point its faultBean attribute to the name of a Java class that has a no-arg constructor, a message String field, and a getter and setter for it. This will be your carrier for that soap:fault detail element.
3. Redeploy your service and regenerate your client. Now the client view will be exactly how you want it. JAX-WS will take any message you supply to your exception type on the server side and put it in the SOAP Fault detail in the SOAP envelope. It will unpack that string message into the fault bean and make it available as the message within the exception you're catching.

Below are examples of using the @WebFault annotation to deal with SOAP faults and exceptions on the web service side.


We still write the method on the service exactly as before--there's no @WebFault annotation on the method--it's a class-level annotation.

    @WebMethod(operationName="verify")
    public @WebResult(name="checkVerifyResponse",
            partName="checkVerifyResponse",
            targetNamespace="
http://www.example.com")
            MessageResponseType
    verify(
    @WebParam(name="check",
        partName="check",
        targetNamespace="
http://www.example.com")
        CheckType check)
        throws CheckVerifyFault {


Now we'll write that CheckVerifyFault class:

@WebFault(name="CheckVerifyFault",
    targetNamespace="
http://www.example.com")
public class CheckVerifyFault extends Exception {

    /**
     * Java type that goes as soapenv:Fault detail element.
     */
    private CheckFaultBean faultInfo;

    public CheckVerifyFault(String message, CheckFaultBean faultInfo) {
        super(message);
        this.faultInfo = faultInfo;
    }

    public CheckVerifyFault(String message, CheckFaultBean faultInfo, Throwable cause) {
        super(message, cause);
        this.faultInfo = faultInfo;
    }

    public CheckFaultBean getFaultInfo() {
        return faultInfo;
    }
}

This class extends Exception, and indicates that it takes a CheckFaultBean. So in Java web services we don't have the luxury of just using any checked exception that we have lying around; we'll have to annotate it, add the constructors that take our Bean info object, and then create that Bean info class. Here's what that looks like:

/**
 * The Java type that goes as soapenv:Fault detail element.
 * Used in web services exceptions, fault beans just hold the details
 * of the SOAP fault. This one is used by the
{@link CheckVerifyFault).
 *
 * @author eben hewitt
 */
public class CheckFaultBean {

    private String message;

    public CheckFaultBean() { }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}


Now you've got something that matches the SOAP semantics better, and we can recompile and redeploy the web service, then regenerate our client artifacts. Because I've renamed the exception class here, I'll need to update my bindings.xml file too, of course.

We also need to use this bean info in our service method. So instead of just throwing exception, we populate the fault bean with the data for the SOAP Fault Detail, and pass that into our exception; JAX-WS will handle the rest.

Here is our update service operation:

public MessageResponseType verify(CheckType check)
  throws CheckVerifyFault {

        LOGGER.debug("Executing verify method in Check web service.");

        if (check == null) {
                final String msg = "The Check cannot be null.";
                LOGGER.debug(msg);
                CheckFaultBean faultBean = new CheckFaultBean();
                faultBean.setMessage(msg);
                throw new CheckVerifyFault("This is the Basic Message.", faultBean);
            }
    //do work...
}

Notice that we create a bean instance, put our message for the client in that, then construct the exception and throw it. We can include two messages: the one associated with the exception string, and the more detailed message that is the string value of the FaultInfo object.

Here is the updated test case. It passes a null parameter to the verify method. That's just the condition the verify method is looking for to throw an exception:

@Test
    public void testException() {
        LOGGER.debug("Executing...");

        CheckType check = new CheckType();

        MessageResponseType response = null;
        try {

            response = checkVerify.verify(null);

            LOGGER.debug("Completed Exception response.");

        } catch (CheckVerifyFault ex) {
            LOGGER.error("Error class: " + ex.getClass().getName());
            LOGGER.error("Caught error. Message: " + ex.getMessage());
            LOGGER.error("Detailed Message: " + ex.getFaultInfo().getMessage());
           
            assertTrue(true);
        }
    }

Running this test gives us just the result that we want:

7/1/09-17:15 ERROR com.example.CheckVerifyServiceTest.testException - Error class: com.discounttire.checkverify.service.CheckVerifyFault
7/1/09-17:15 ERROR com.example.CheckVerifyServiceTest.testException - Caught error. Message: This is the Basic Message.
7/1/09-17:15 ERROR com.example.CheckVerifyServiceTest.testException - Detailed Message: The Check cannot be null.

...
BUILD SUCCESSFUL
------------------------------------------------------------------------
Total time: 10 seconds
Finished at: Wed Jul 01 17:15:54 MST 2009
Final Memory: 25M/153M

Now you can see that:
1. The test actually allows a totally natural client feel for using Java exceptions and SOAP faults.
2. The string that we populated the exception with on the service-side is readily visible to the client.
3. We get both the regular string message in the exception, and the detail in the fault info bean.

To read more about Java web services and SOAP, pick up a copy of my new  book, Java SOA Cookbook from Amazon.


 

July 01, 2009 in Tech Notes | Permalink | Comments (6)

Installing OpenESB Components

OpenESB only comes with a number of useful ServiceEngines pre-installed when you get the NetBeans 6 download with the SOA pack. Say you want to install OpenESB separately. You might do this because you 1) want clustering and 2) have a headless environment and 3) don't want an IDE on the target box or 4) blah blah blah.

You may be surpised to discover that the only two components that are pre-installed with OpenESB 2 are the sun-http-binding and the sun-javaee-engine. If you want to execute a BPEL, you'll need that engine.

To see what you have installed, open the GlassFish console and point to JBI > Components and they'll all be listed there.

If you need to get more components, such as the BPEL engine, you can get them from here:

https://open-esb.dev.java.net/Downloads.html

Scroll down to the section called OpenESB Component Downloads. This link lists the service engines and binding components you need. Download your item and drop it in the

<glassfish>/domains/<domainname>/jbi/autoinstall directory

And it will install automatically.

December 31, 2007 in Tech Notes | Permalink | Comments (0)

Solving BPEL Project Deployment Error (network downloads disabled) with XML Catalogs

You may see the Exception "Could not load resource" and then the name of your XSD with the reason that "network downloads disabled" when trying to deploy an apparently valid BPEL JAR inside a composite service assembly for JBI. 

If you are using NetBeans 6, this is easy to solve; it is also quickly solvable manually.

In NetBeans, right click on the project and choose "Populate Catalog", which creates a file at the root of your project called catalog.xml. This can also be created by hand if you're using Eclipse. The purpose of an XML catalog, which is an OASIS-OPEN standard, is to resolve remote files to local copies in order to reduce chatty network traffic and to keep your XML documents appropriately organized despite your location.

So your catalog will resolve the remote or absolute names in your XML documents to the local copies within your CASA Service Endpoint (SE), like this:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" prefer="system">
    <system systemId="http://localhost:7070/CustomerManagementService/CustomerManagement?wsdl" uri="src/localhost_7070/CustomerManagementService/CustomerManagement.wsdl"/>
    <!-- etc.. -->
</catalog>

Replace the "src" prefix in the URI with the location of your local copy relative to the JARred composite app you're deploying.

Modify your build file to copy the catalog.xml file into your deployable JAR's META-INF folder.

This should not only make your app actually deploy, but using the catalog.xml file should help separate the physical location from the abstract location and make things like validation faster.

You can read more about XML Catalogs here: https://jax-ws.dev.java.net/nonav/2.1.2m1/docs/catalog-support.html

Note too that if you're using XMLBeans, you can flip the flag on the xmlbean Ant task download=true. If you're using XJC like I am then you don't have such a flag available.

October 09, 2007 in Tech Notes | Permalink | Comments (0)

Unable to create JAXBContext due to the security restriction Revisited

I have written on this elliptical error before, but find that there are a variety of causes for it. This can happen at deploy-time in Glassfish. The com.sun.enterprise.deployment.backend.IASDeploymentException and accompanying stack trace all but entirely mask the true root cause of the problem, so I will describe here at least one thing to check for.

Perhaps you are using bare (not wrapped) document/literal Web Services. Your WebMethod has the @SOAPBinding(parameterStyle=SOAPBinding.ParameterStyle.BARE) annotation. If you attempt to return a List type from this method, you could see the "Unable to create JAXBContext due to the security restriction" error. Say your EJB or servlet signature wants to be this: public List<Product> getProducts(). The problem is in your return because your message won't be unmarshallable.

It seems logical enough to assume this might work, because "xs:list" is a built-in schema type. But if you are using straight dispatch like this:

Dispatch<SOAPMessage> dispatch = service.createDispatch(portQName, SOAPMessage.class, Service.Mode.MESSAGE);

...and not generated types you would get from wsimport and the Service classes, then this won't happen automatically.

Also, schema lists allow only simple element types, so you can't define a list and hope the Products (or whatever your complex custom type is) will automatically make it in.

What you need to do is make a new Schema to act as your return type that sets the "maxOccurs" attribute to unbounded for your custom type:

    <include schemaLocation="Product.xsd" />
   
    <element name="products" type="myns:ProductList"/>
   
    <complexType name="ProductList">
        <sequence>
            <element name="products" type="myns:Product"
                maxOccurs="unbounded" nillable="true" />
        </sequence>
    </complexType>

So now your service implementation method signature looks like this:

public ProductList getProducts()

This will generate a read-only Java type that allows you to get the internal array list of Product objects, and your error will go away and your problem will be solved.

The downside is that you have another schema to maintain. The upside is, that's what we do when we say we want to be bare document/literal, we just want to exchange business documents, and we get to be accountable for our work in our schemas.

October 05, 2007 in Tech Notes | Permalink | Comments (0)

Using A Sequence for an EJB 3 Entity Bean with i/5 iSeries DB2

This little note shows you how to write an EJB 3 Entity Bean using CMP with an auto-generated primary key incrementing as a sequence. While I assume familiarity with EJB 3 Entity Beans, this illustrates specifically how to identity a primary key in your application using the sometimes finicky iSeries DB2.

This setup uses iSeries DB2 v5R3 as the database, Glassfish v2 beta as the application server.

Download the jt400.jar from the open source IBM JTOpen Toolbox. Version 6 was just released.
Add it to your server classpath.

When you set up your connection pool, the DataSource class name is:

com.ibm.as400.access.AS400JDBCDataSource

Create an Additional Property called "naming" and set its value to "system". By default, the naming
is set to "sql", which means that you specify in your SQL code using dot syntax the library in which
your files (tables) can be found:

SELECT * from MYLIB.MYFILE

While SQL naming works fine and is convenient, you will in all likelihood have different library names on production than you will on QA than you will on DEV, etc, and you don't want library names hardcoded in your SQL as a result. Otherwise you'd have to replace them when you build for different environments.

So setting naming to "system" allows you to specify an additional property, "libraries", which lists the libraries you want the driver to search within to find your files. So create a new property on the Connection Pool called "libraries" and set its value to a comma-separated list of all your libraries in which you want it to search in your different environments. Then you can write this in your SQL:

SELECT * from MYFILE

...and your driver will look in the order specified in your list to find the file.

Now set up the table that your entity will represent. Note that if you use CRTLIB to create the schema for your table instead of STRSQL, you may get the following error:

error message: java.sql.SQLException: [SQL7008] table_name in database_name not valid for operation.

Exception [TOPLINK-4002] (Oracle TopLink Essentials - 2.0 (Build b53-rc (06/27/2007))): oracle.toplink.essentials.exceptions.DatabaseException
Internal Exception: java.sql.SQLException: [SQL7008] TABLE in LIB not valid for operation.
Error Code: -7008

You may be able to resolve this by enabling journaling for your library and the tables contained in it. Journaling logs a record of the operations performed so you can roll back.

Exception [TOPLINK-4011] (Oracle TopLink Essentials - 2.0 (Build b53-rc (06/27/2007))): oracle.toplink.essentials.exceptions.DatabaseException
Exception Description: Error preallocating sequence numbers.  The sequence table information is not complete.

That's because TopLink does not support native sequencing in IBM DB2 databases. You have to use a table and do your sequencing that way. Luckily there are EJB 3 annotations to assist you in this.

If you have a SequenceGenerator defined in your bean like this:
@SequenceGenerator(name="preAppSequence", sequenceName="SEQUENCEPF", initialValue=1)

remove it, and use TableGenerator instead, as shown below.

Our primary key field in the entity bean implementation is called "id":

@Entity //...

   

@Id
    @Column(name="ROWID", unique=true)
    @GeneratedValue(strategy=GenerationType.TABLE, generator="mySequence")
    @TableGenerator(name="mySequence", table="SEQUENCEPF",
        pkColumnName="FNAME", pkColumnValue="MYENTITYNAME", valueColumnName="FKEY",
        allocationSize=1, initialValue=1)

    private Long id;

    public Long getId(){
        return id;
    }

    public void setId(Long id){
        this.id = id;
    }
    //...

Create a separate file called "SEQUENCEPF". It has two columns, one that holds the name of the entity ("FNAME") for which you are generating primary keys. Its first row value should match your entity name (pkColumnValue="MYENTITYNAME").

The second column is called "FKEY" and holds the highest value that has been allocated for a primary key for that entity so far. Incrementing this value is what Java takes care of for you. Because these are our names and not the default, we need to override them in the @TableGenerator annotation.

The default is
SEQ_NAME, which specifies the class type to which the selected row refers
SEQ_COUNT, which specifies the highest sequence number currently allocated for the object represented in the selected row

But our driver doesn't appear to like underscores, so we specify our own.

Such a primary key solution is portable across servers. In later versions of DB2 there are
hidden options available, but this solution is clear, straightforward, and portable.

Seed your table with the first value using a straight insert, because Java will execute a SQL Statement like this:

UPDATE SEQUENCEPF SET SEQ_COUNT = SEQ_COUNT + ? WHERE SEQ_NAME = ?

So you want to have something there to add to. Note that we set the allocationSize, because for some reason it's set to 50 by default. Then you should be all set.

September 11, 2007 in Tech Notes | Permalink | Comments (0)

Using Interfaces in EJB 3, Packaging and Deploying, and Solving the "Cannot resolve reference Unresolved Ejb-Ref" Error

There is some confusion regarding the use of @Local and @Remote annotations and the use of interfaces generally in EJB 3 because of some flexibility in their use.

The purpose of this post is to clarify two related things:
1) Do you really need that interface for your EJB? Or just sometimes? When?

2) How do I solve the "Cannot resolve reference Unresolved Ejb-Ref" that I'm probably getting if I stumbled across this post? Might they be related?

In Glassfish, you can deploy and use an EJB with absolutely no interface whatsoever. It can back a Web Service, which you can invoke and use without issue. That's because you don't have any clients trying to invoke methods on your stubs.

So if you have a Session bean that you are _only_ using to back a Web Service, then I recommend that you _don't_ create an interface for it. The reason is that if you're going to the trouble of making a Web Service, you probably want people accessing it as a Web Service, and not trying to invoke it directly as if it were a regular EJB. Because reading is often harder than writing code, having unnecessary stuff around might just make things harder to maintain.

So that's one case in which you don't need the interface.

However, on a related matter, if you're using EJB 3, you may have seen this error during deployment: "Cannot resolve reference Unresolved Ejb-Ref"

Say you have this structure: an EAR that contains a WAR and an EJB-JAR. You even thought ahead and did the standard thing and put classes that both the EJB-JAR and the WAR will need (common models, exceptions, utility classes, whatever) in a "lib" directory off of the root in order to get your classloaders working properly. You made sure that you only have Web classes in your WAR (listeners, filters, servlets, etc, things that only work on the Web). You made sure you don't have any Web things in your EJB-JAR.

You made sure you _didn't_ just blindly copy shared classes all over your poor EAR like Tony Montana spraying an AK-47 full of utilities and domain models and exceptions into every possible deployment artifact and crossing your fingers hoping that the classloaders just magically work (uh, don't count on it--even if it works for a while).

So instead you put those things in the <EAR-ROOT>/lib directory. Perfect. And now that the EAR's "lib" directory is standardized (thank you very much, BEA, for APP-INF, which laid the groundwork for this long-overdue feature), you don't need references in your Manifest.MF files anymore--the classloaders will just pick everything up.

So you did all of this but you still have this error that you can't deploy because of this "Cannot resolve reference Unresolved Ejb-Ref".

This one might have you thinking that you need to restructure your Ant script in order to provide something like a client JAR that contains the interfaces (only--not the impls!) for your EJBs and put that in the Web tier. The answer is easier than that.

You might also be thinking that you need to modify your deployment descriptors and override something there--but if you're like me, you're just using annotations and you don't want to start mucking around with descriptors anymore. You definitely don't need to do that.

So here's what to do:

Just put this code in your servlet (or listener or filter (?!!) or whatever):

   

@EJB
    MyBeanInterface myBean;

You do NOT have to specify the class, comme ca:

   

@EJB(MyBeanInterface.class)

First thing is to make sure that you don't actually have any bean implementation classes anywhere in your WAR. That would be a Bad Thing. That violates all laws of enterprise classloaders, and I believe two minor laws of physics.

The solution is that you must have an interface for your EJB, even though they will compile and deploy and run a whole big important Web Service without one (see above).

Also, it doesn't matter if your interface contains your @Local or @Remote annotation or if your bean class does.

Many books and articles on EJB 3 show an interface that contains the @Local or @Remote annotation, but everything will work fine if you leave these annotations in your bean implementation class. This is preferable perhaps because it allows your interface to really be a true O-O interface. That is, to use the annotation in the interface destroys the purpose of interfaces in the first place, which is to define a contract, staying silent on implementation details; indicating that your interface is part of an EJB undermines this purpose precisely by revealing this dependency and coupling clients to it.

This is perhaps academic fussiness, because if your interface is no longer implemented by an EJB, it's no longer a managed resource and not a candidate for injection, and so your client will have to change _anyway_.

So I still come down on the side of "put your @Local annotation in your bean implementation and not your interface", for the simple sake of trying to focus on Thinking in Interfaces and not implementations.

August 30, 2007 in Tech Notes | Permalink | Comments (2)

Using Custom Bindings in JAX-B 2.0 to Generate a Wrapper Class for a SimpleType

Perhaps when you were a child, you dreamed of one day being big. Perhaps you would lie in the warm summer sun, bare toes dangling in a lazy stream, daydreaming that even you, yes, you, one day could encounter someone who might solve that core, universal human mystery of how to create value object wrapper classes in Java from XML Schemas defining simple content types using custom inline bindings in JAX-B 2.0.

Oh, lucky day...

So. You have a value object defined in an XML Schema that
you want to create as a full-blown object when creating Java objects from JAX-B 2.0. By default, JAX-B will substitute simple types where it can.

USPhone is such a class for me. My schema for USPhone is like this:

<schema xmlns="http://www.w3.org/2001/XMLSchema"
        targetNamespace="http://ns.my.com"
        xmlns:x="http://ns.my.com">

     <annotation>
        <documentation xml:lang="en">
            United States phone number, restricted with parens and hyphens optional.
        </documentation>
    </annotation>

    <simpleType name="USPhone">
        <restriction base="string">
            <pattern value="\(?[2-9]\d\d\)?[ -]?[2-9]\d\d-\d{4}" />
            <minLength value="10" />
            <maxLength value="16" />
        </restriction>
    </simpleType>
</schema>

So it's really just a String, and JAX-B knows that, and as a consequence doesn't generate a whole class for it; callers just see that property as a String.

It can be confusing, because even if your referencing schema (say, Customer) holds a phone value that you define as

    <complexType name="Customer">
        <sequence>
            <element name="homePhone" type="x:USPhone" minOccurs="0" maxOccurs="1"/>
            ...

...at generation time, your beautiful x:USPhone type will be lost to the ravages of JAX-B type simplification. The enclosing Customer object will just hold a string for homePhone.

But what if you don't want that simplification, and do want a whole class generated,  considering that you went all that trouble defining the bloody USPhone.xsd in the first place?

This is very easy to turn on and off in JAX-B. You can do it with an internal or external annotation to your calling schema. This is the money shot:

<schema xmlns="http://www.w3.org/2001/XMLSchema"
        targetNamespace="http://ns.my.com"
        xmlns:x="http://ns.my.com"
        xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
        jxb:version="1.0">

    <annotation>
        <documentation xml:lang="en">
            Represents a Customer...
        </documentation>
        <appinfo>
            <jxb:globalBindings mapSimpleTypeDef="true" />
        </appinfo>
    </annotation>

The mapSimpleTypeDef attribute is set to false by default, which means that JAX-B will just generate your painstakingly-defined type to whatever it wraps, such as String, if it can.

Setting it to true means that you will get a full blown class generated for your schema type.

I do not get to keep my regular expression here, but it will create a value object like that looks like this:

/**
* <p>Java class for USPhone simple type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* &lt;simpleType name="USPhone">
*   &lt;restriction base="{http://www.w3.org/2001/XMLSchema}string">
*     &lt;pattern value="\(?[2-9]\d\d\)?[ -]?[2-9]\d\d-\d{4}"/>
*     &lt;minLength value="10"/>
*     &lt;maxLength value="16"/>
*   &lt;/restriction>
* &lt;/simpleType>
* </pre>
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "USPhone", propOrder = {
    "value"
})
public class USPhone {

    @XmlValue
    protected String value;

    /**
     * Gets the value of the value property.
     *
     * @return
     *     possible object is
     *     {@link String }
     *    
     */
    public String getValue() {
        return value;
    }

    /**
     * Sets the value of the value property.
     *
     * @param value
     *     allowed object is
     *     {@link String }
     *    
     */
    public void setValue(String value) {
        this.value = value;
    }

}

This is what I want for my particular use case and setup.

If you want to specify such exciting JAX-B binding customizations and more, you might want to check out this tutorial: http://java.sun.com/webservices/docs/2.0/tutorial/doc/JAXBUsing4.html.

Be careful, though, because it is about an earlier version of JAX-B, and some things are no longer valid. For example, this has been removed:

<jxb:globalBindings bindingStyle="modelGroupBinding"/>

Argh.

On a related matter, it's up for debate whether internal (inline) or external binding directives are better. They work either way. I've shown the inline version here for brevity and clarity.

Inline customizations have the advantage of being easy to use, requiring no modification of your Ant script or XJC task if you change them or take them out altogether.

They have a disadvantage inasmuch as they "pollute" your otherwise pure XML Schemas with not only Java-specific code, but JAX-B specific code. While it's not going to kill anybody who might be using Python instead of Java, it's generally a bad practice to expose implementations like this.

Keeping your binding customizations in an external bindings file is appealing aesthetically. It achieves our usual goal of high cohesion--that one file does just that one thing. It keeps our schemas fresh for porting everything to .NET later if we want. It has the disadvantage of being a little harder to set up, but that's a one-time hit.

One issue with both of them of course is the same as with any customization: if you change implemenations later (say, to Castor), your binding customizations are now invalid, even though your schema isn't. So be very clear as to what your implementations depend on, and what you really have control over.

Good luck.

August 24, 2007 in Tech Notes | Permalink | Comments (0)

My New Favorite Error in Schema Validation

Something amazing happened to me today during schema validation. This is my new favorite all time error:

Error: src-ct.2.1: Complex Type Definition Representation Error for type 'USPhone'.

When <simpleContent> is used, the base type must be a complexType whose content type is simple, or, only if restriction is specified, a complex type with mixed content and emptiable particle, or, only if extension is specified, a simple type. 'string' satisfies none of these conditions.

Sheesh. I feel so dopey. Only a moron would think that 'string' would be valid as a simple content with a base type of complexType whose content type was simple. Bad programmer! I can't even satisfy one of its conditions! Bad programmer!

August 22, 2007 in Tech Notes | Permalink | Comments (1)

Reading, Updating, and Writing Values in an XML File with Java

At my company we are frequently in need of Java programmers. It's a terrific place to work, and we are undergoing a good deal of growth. As a result, my colleagues and I spend a considerable amount of time interviewing. We take very seriously whom we hire, but we're looking for a way to make the process less time consuming for us and more objective.

So I recently started writing a Java application that automates the process of setting up an environment for candidates to write real code in and build their work at the end. I needed a general-purpose way to take some boilerplate XML files and update certain values in the files based on candidate information, such as their name.

I wrote this utility that does just that. You pass it the name of the file you want to update, an XPath expression that finds the nodes you're interested in, and then your new value. It reads in your XML file and  updates the nodes corresponding to your XPath, then immediately writes the  entire file out again.

It uses DOM, so it is perfect for easily updating Ant build scripts or any kind of configuration files during the automation of some setup that happens routinely, which is exactly what I'm up to here.

I'm using Java 6, but the XPath stuff was new in 5, so that's the earliest version you could use.

    /**
     * Changes a value in an XML file on the path to the value passed in. The
     * node to update can be either an element or an attribute. If you want to
     * update an attribute, just pass <code>null</code> for it and the parser
     * will look just for the matching element name. Not intended to solve every
     * XML update problem, but just handle some of the boilerplate in certain
     * cases.
     * <p>
     * <b>Examples:</b><br/>
     * <pre>
     *
     * &quot;/project/@name&quot; (update the value of the &quot;name&quot;
     * attribute in the &quot;project&quot; element.)
     *
     * &quot;/project/test[last()]/@dude&quot; (update the value of the
     * &quot;dude&quot; attribute in the last element called &quot;test&quot;)
     *
     * &quot;/project/test[@price&gt;50.00]&quot; (update the value of the test
     * content for all test elements that have an attribute called &quot;price&quot;
     * whose value is greater than 50.00 )
     *
     * &quot;/project/test[@price&gt;50.00]/@dude&quot; (update the value of the
     * &quot;dude&quot; attribute for all test elements that have an attribute
     * called &quot;price&quot; whose value is greater than 50.00 )
     *
     * &quot;/project/test[@dude='old']&quot; (update the value of the
     * &quot;test&quot; element for all test elements that have an attribute
     * called &quot;dude&quot; whose value is equal to the string 'old')
     * </pre>
     * </p>
     * <p>
     * This implementation uses DOM, so it may not be suitable for very large
     * (many megabyte) files.
     *
     * @param fileIn  the available XML file you want to update.
     * @param fileOut the available XML file that will be written out, which can be
     * the same as the <code>fileIn</code>.
     * @param xpathExpression the valid XPath expression to determine which
     * nodes will get updated.
     *
     * See <a href="link http://www.w3schools.com/xpath/xpath_syntax.asp">W3
     * Schools XML Tutorial</a> for details on XPath syntax.
     * @param newValue the string you want to set this tag or attribute to.
     * @throws IOException if anything goes wrong, this wraps all of the
     * other exception types possible from setting up the factories and
     * transformers.
     */
    public static void updateValueInXmlFile(String fileIn, String fileOut,
            String xpathExpression, String newValue) throws IOException {

        //Set up the DOM evaluator
        final DocumentBuilderFactory docFactory =
            DocumentBuilderFactory.newInstance();

        try {
            final DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
            final Document doc = docBuilder.parse(fileIn);

            final XPath xpath = XPathFactory.newInstance().newXPath();
            NodeList nodes = (NodeList) xpath.evaluate(xpathExpression, doc,
                    XPathConstants.NODESET);

            // Update the nodes we found
            for (int i = 0, len = nodes.getLength(); i < len; i++) {
                Node node = nodes.item(i);
                node.setTextContent(newValue);
            }

            // Get file ready to write
            final Transformer transformer =
                TransformerFactory.newInstance().newTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");

            StreamResult result = new StreamResult(new FileWriter(fileOut));
            transformer.transform(new DOMSource(doc), result);

            // Write file out
            result.getWriter().flush();
            result = null;

        } catch (XPathExpressionException xpee) {
            LOGGER.error(xpee);
            throw new IOException("Cannot parse XPath.", xpee);
        } catch (DOMException dome) {
            LOGGER.error(dome);
            throw new IOException("Cannot create DOM tree", dome);
        } catch (TransformerConfigurationException tce) {
            LOGGER.error(tce);
            throw new IOException("Cannot create transformer.", tce);
        } catch (IllegalArgumentException iae) {
            LOGGER.error(iae);
            throw new IOException("Illegal Argument.", iae);
        } catch (ParserConfigurationException pce) {
            LOGGER.error(pce);
            throw new IOException("Cannot create parser.", pce);
        } catch (SAXException saxe) {
            LOGGER.error(saxe);
            throw new IOException("Error reading XML document.", saxe);
        } catch (TransformerFactoryConfigurationError tfce) {
            LOGGER.error(tfce);
            throw new IOException("Cannot create transformer factory.", tfce);
        } catch (TransformerException te) {
            LOGGER.error(te);
            throw new IOException("Cannot write values.", te);
        }
    }

August 10, 2007 in Tech Notes | Permalink | Comments (1)

BPEL Selection Failure Fault

If your application throws a selectionFailure fault, it may be the case that you have an error in your implementation. I have an EJB implementation behind my service endpoint that had a String field that was not getting initialized in a certain circumstance. My test case reported a selectionFailure fault, which is usually associated with a copy operation during an assign activity.

So if you're getting this exception, check your assignments first to make sure they're all there, but make sure your implementation didn't change too.

July 11, 2007 in Tech Notes | Permalink | Comments (0)

Fail to load schema types Error in NetBeans milestone 10

If you are using NetBeans milestone 10, perhaps you have seen this error: "Fail to load schema types from" and then a file path pointing to the WSDL you're trying to generate a test case for.

If you are working with the Glassfish ESB you might want to create a test case to ensure that, say, your BPEL process is invoked. Everything could be set up properly, but when you try to create the test, NetBeans won't let you. If you're new to the stuff, you could think the problem is on your end--it's not.

The thread at http://www.nabble.com/Error:-Fail-to-load-schema-types-t3317880.html indicates that this was a bug in NetBeans several months ago, but has since been fixed.

The whole story is that this was a bug in NetBeans 6.0 milestone 8, got fixed in milestone 9, and got broken again in milestone 10. So how do you work around it if you're using the latest version of NetBeans 6 (milestone 10)?

The workaround posted at that site is not ideal because while you can get through the wizard by commenting out the schema imports, your test SOAP envelope will be empty, because you've dereferenced your schemas, so what's the point.

The way I got around it is to use NetBeans 6 milestone 9 to generate the test case, because it doesn't have the bug. Then I can execute the tests normally in Milestone 10 after they've been created.

July 11, 2007 in Tech Notes | Permalink | Comments (1)

Using Microsoft SQL Server with Apache jUDDI

jUDDI is an implementation of the UDDI version 2 spec that stores metadata on web services. We're using it for a private registry, and JBoss is rolling it into their product. The strange thing about it is that a Release Candidate was published in 2005, but never graduated to a full 1.0 release.

I have jUDDI running on MySQL v5, which is one of the several databases it is compliant with out of the box. But we programmers aren't the only people in IT, and it would be polite to those at the other end of our floor to do what we can to not introduce additional platforms if we can help it. So I made a perfunctory pass at getting jUDDI to work with MS SQL Server 2000, with unhappy results.

In order to use Microsoft SQL Server 2000 with jUDDI, you need to make some source changes and recompile. That's because MS SQL Server disallows the definition of two TIMESTAMP typed columns within a single table.

But if you really want to make it work, the obvious thing is to modify the jUDDI set up script to use DATETIME when setting up the AUTH_TOKEN table instead of TIMESTAMP, because you can define an arbitrary number of those within a single table). But Microsoft states that DATETIME is not supported as an equivalent. Moreover, once you attempt to access your registry, you'll get the following error:

2007-07-09 10:42:16,742 [http-8080-Processor25] ERROR org.apache.juddi.function.SaveBusinessFunction  - java.sql.SQLException: Disallowed implicit conversion from data type datetime to data type timestamp, table 'uddi.uddiuser.BUSINESS_ENTITY', column 'LAST_UPDATE'. Use the CONVERT function to run this query.

So you'd need to get the jUDDI Java source to convert your TIMESTAMP calls to create a DATETIME just for accessing the AUTH_TOKEN table, modify the data accessor, recompile, and redeploy. The obvious downside here is that you'll have to do extra work to ensure you're stil compatible with MySQL. The trade off isn't great here. So the question becomes one of long-term maintenance. I think we'll quietly stick with MySQL for this.

July 09, 2007 in Tech Notes | Permalink | Comments (0)

Discovering which JAR file Contains a Class you're Looking For

Did you ever have a build complain that you don't have a class on your classpath that you need and although you'd be delighted to comply and put the class on your classpath, you don't know what JAR it's in? Here is a way to find the needle in the haystack.

Here we'll use an example involving Glassfish, because this seems to happen on server-side projects that involve a great number of different JARs (web services requires JAXB, XJC, WSImport, JUnit, the Ant tasks that go with them, and so forth, for example). You want only the JARs that you actually need on your cp, not hundreds of modified bundled versions of things on your cp that may or may not be in use--which is what some IDEs do.

If your build doesn't work because, say, an Ant task that wraps some program such as XJC complains that it can't find a class like "com/sun/enterprise/cli/framework/InputsAndOutputs.class" you need to find that class. You can tell from the name that it's provided by Sun, and can look in the Glassfish lib directory and just use the brute-force method of opening JARs one by one and eyeballing it. But if you open the lib directory of Glassfish (or WebLogic 10 or Spring or anything these days), there are dozens of JARs in there! It can be really boring and time-consuming to determine which JAR has the class you want.

You don't know what this class does. You don't even care about this class at all. You just need your XJC Ant task to work and apparently some class in there needs some other class that needs this one.

But it's not a good practice to throw all of the JARs in there on your cp--it is slow and misleading and doesn't help learn you about what's happening under the hood. And in my view it is not good to be dependent on the IDE whatsoever. You should be able to execute ant from the command line and your build should still work. I can't tell you how many Ant scripts I've seen whose authors claim that their projects will run outside of their IDE, and they don't because they have conflated the IDEs paths with their Ant paths. That drives me nuts.

So, on a Linux system, the following command will examine all of the Jar files in the current directory and print their contents to a file called "tmp".

find . -name "*.jar" -print -exec jar -tvf {} \; > tmp

The resulting file looks like this:

./appserv-deployment-client.jar
     0 Tue Apr 24 07:21:00 MST 2007 META-INF/
   449 Tue Apr 24 07:20:58 MST 2007 META-INF/MANIFEST.MF
     0 Tue Apr 24 06:45:36 MST 2007 com/
     0 Tue Apr 24 06:45:34 MST 2007 com/sun/
     0 Tue Apr 24 06:45:34 MST 2007 com/sun/enterprise/
     0 Tue Apr 24 06:45:42 MST 2007 com/sun/enterprise/admin/
     0 Tue Apr 24 06:45:42 MST 2007 com/sun/enterprise/admin/common/
     0 Tue Apr 24 06:45:38 MST 2007 com/sun/enterprise/admin/common/exception/
   645 Tue Apr 24 06:45:28 MST 2007 com/sun/enterprise/admin/common/exception/AFException.class
     0 Tue Apr 24 06:45:42 MST 2007 com/sun/enterprise/admin/util/
  1821 Tue Apr 24 06:45:28 MST 2007 com/sun/enterprise/admin/util/HostAndPort.class

...and so on.  Each JAR will be named, followed by all of the packages and classes in it. So you can then use the "less" tool to find your guy.

Within the "less" tool, type:
> /InputsAndOutputs

to search down the contents for the "InputsAndOutputs" class. This will find and highlight that text (as long as the JAR that contains your class actually was in the directory you ran this command from).

Now all that's left is to search up the file for the first instance of ".jar" and that will be the name of the JAR file containing your class:

>?.jar

This highlights "./admin-cli.jar", which is indeed the Glassfish JAR file containing InputsAndOutputs.class. So now I can drop that on my classpath and get on with my build.

If you don't know what JAR file contains a class you're looking for, this is an easy way to deal with it on Linux. Don't forget to delete the "tmp" file if you don't want to leave it around for another time.




June 07, 2007 in Tech Notes | Permalink | Comments (2)

Dealing with the "Unable to create JAXBContext due to the security restriction" error in Glassfish.

My colleague Kevin and I are working on the Service Oriented Architecture team at our retail employer. The idea is to pilot a project to get us going for real down the SOA road. We're evaluating tools like Aqua Logic, WebLogic 10, and Sun's Glassfish, and working with the new APIs in Java SE 6 and Java EE 5, including JAXB 2.0, JAX-WS to build services, and so forth. So I thought I would post some of our fidings here every once in a while that might be useful to others working with similiar technologies.

We have a WebService that accepts a complex custom type, and returns a String. The service is an EJB 3 Stateless Session Bean, and we're using simple Java models for a "Start from Java" development process. We're agreed that we won't add annotations or anything to the classpath that isn't absolutely necessary. We don't even have an interface for our EJB, because you don't need it (let alone leaking the implementation out to the interface with @Local or @Remote, rendering the presence of the interface itself totally redundant and useless qua interface).

We decided to wrap the String that our operation returns in more useful custom type (called BinInfo), and suddenly our Ant deployment task (for Glassfish b47) died with the following error:

The exception message is: CLI171 Command deploy failed : Deploying application in domain failed; Unable to create JAXBContext due to the security restriction

It seemed our WebService could somehow accept a custom type, but not return one. What was the problem? Looking on the Glassfish forum revealed that other users had a similar problem, but their solutions didn't work for us. Posts there indicate that 1) you need to have a default no-arg constructor in custom types you use as parameters or return types in your web service operations, including Sun-provided classes like Locale and 2) that the deploy-time exception does not get reported properly by Glassfish. So if your class does, as ours does, really have a default no-arg constructor, you could be flummoxed. This is all standard XML marshalling stuff, so what to do?

There are two ways to deal with this situation. If your problem is the no-arg constructor situation, you can add one and see if that clears it up. There are obvious design reasons not to  blindly go that route, however.

Second way: if that's your problem but it's not in a class you wrote or can change or want to change, you can use the standard Java SE 6 annotation @XmlJavaTypeAdapter(YourAdapterImpl.class) to indicate to the marshaller exactly how it should deal with this absence. There is a concise and helpful article on the subject here, so I won't go into it:

http://weblogs.java.net/blog/kohsuke/archive/2005/09/using_jaxb_20s.html

But what if you do, as we do, actually have a default no-arg constructor, have an object simple enough that creating a new class to implement @XmlJavaTypeAdapter is overkill (not to mention misleading for future maintainers of the code and does not address the root of the problem) and the error message is hidden from you? Directly use the tool that Glassfish uses under the hood: schemagen.

If the Java tools in the JDK bin directory are on your path (they should be) then you can open a prompt, type "schemagen" and use that tool to generate your XML schema representation. Navigate to the directory with the Java source file that is giving you problems. For us it was BinInfo.java.

Here was our class:

public class BinInfo {

    public String chargeType;

    public BinInfo() { }

    public void setChargeType(String chargeType) {
        this.chargeType = chargeType;
    }

    public String getChargeType() {
        return chargeType;
    }   
}

A perfectly normal, simple bean, right?

Running schemagen BinfInfo.java produced the following error:

[ehewitt@dtc20266w domain]$ schemagen BinInfo.java
error: Class has two properties of the same name "chargeType"
        this problem is related to the following location:
                at mypackage.BinInfo.getChargeType(BinInfo.java:28)
                at mypackage.BinInfo(BinInfo.java:16)
        this problem is related to the following location:
                at mypackage.BinInfo.chargeType(BinInfo.java:18)
                at mypackage.BinInfo(BinInfo.java:16)
1 error

This reveals that the field was accidentally typed to be "public", and schemagen thinks that the field itself and the getter method for it are the same. I changed the visibility of the field to private and everything worked fine.

While hopefully your typing skills are better than mine, this post is meant to illustrate that you can use schemagen to get a clear picture of what the deployment tools are doing, and highlight mistakes in your code. This is important because Glassfish isn't percolating nested exceptions up at this time, and the error messages are misleading at best ("the security restriction"???) .

May 30, 2007 in Tech Notes | Permalink | Comments (6)

WebLogic 10 License Bug Prevents Startup

If you are getting an error like this:

java.lang.RuntimeException: There were errors initializing your configuration: com.solarmetric.license.LicenseException: Your license key "376D-896F-8B43-BE3D-3D00" expired on "5/14/07 5:00 PM". Please contact [email protected] for purchase or evaluation information.

...this is a known bug. This will affect you only if you downloaded WebLogic 10 before May 14, as I did. You need to get the patch from BEA or you'll never be able to start WebLogic. Just go through the process of getting the evaluation copy again, and they'll give you some options. Hopefully this saves a few headaches.

May 16, 2007 in Tech Notes | Permalink | Comments (1)

Query for Finding A String in Your MS SQL Stored Procedures

Here is a query that you can execute in MS SQL Server's Query Analyzer to find some text string in any stored procedure defined in your database. This is very useful if you change the name of a table or something like that, and need to know what procedures to udpate.

declare @textToFind varchar(300)
set @textToFind = 'Store'

SELECT ROUTINE_NAME, ROUTINE_DEFINITION
FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_DEFINITION LIKE '%' + @textToFind + '%' AND ROUTINE_TYPE='PROCEDURE'

It returns a list of the names of all stored procedures that contain your text string.

January 12, 2007 in Tech Notes | Permalink | Comments (0)

Annotation for Java Code Reviews and Stripes

I wrote this annotation to assist our team in keeping track of our many ongoing code reviews, and just made it part of my new Java file template in Eclipse. It is not a big deal, but I have found it sort of useful as time goes on. Just compile it and include in your Java source files like this:

@Reviewed(stage=Reviewed.Stage.Passed, date="1/2/07", reviewers={"BM,MM"}) public class Foo {}

I love annotations in Java, and have recently become interested in the Stripes project, which is a Web framework that is very lightweight and not as intrusive as something like Struts:

http://stripes.mc4j.org/confluence/display/stripes/Home

I mention it because Stripes makes extensive use of annotations. Sorry for the low-cohesion of this post. :)

package com....;

import static com....Reviewed.Stage.New;

import java.lang.annotation.*;

/**
* Used at the class level to indicate that a Java source file has been
* undergone code review, or needs to. This serves a few purposes:
* <ol>
* <li>It allows readers of the source to guage the level of quality that they
* might be able to expect from the code
* <li>It allows code reviewers to know what classes have already been reviewed
* so that they can review new code next time.
* <li>It allows supervisors to guage the level of review coverage in the
* repository.
* <li>It allows tools to search the repository to generate reports.
* <p>
* Because the Documented annotation is used, code with this annotation will
* appear in JavaDocs generated for source that uses it.
* <p>
* The obivous downside to using this is that it requires projects to either 1)
* acquire a possibly unnecessary dependency on the Shared project or 2)
* duplicate the code for this annotation in their own project.
*
* @author Eben Hewitt
* @since 1.0
*/
@Documented
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface Reviewed {

/**
  * Indicates through what point in the progression through code reviews this
  * Java source code has successfully moved.
  *
  * @author Eben Hewitt
  * @since 1.0
  */
public enum Stage {
 
  /**
   * This code has not yet been reviewed, and should be; this is the
   * default value if none supplied.
   */
  New,
 
  /**
   * This code has been reviewed, and needs some tuning, which should
   * be underway.
   */
  Revising,

  /**
   * This code has been reviewed, and the reviewers indicated in
   * {@link #reviewers} find this code of highest quality.
   */
  Passed};

/**
  * The current stage that this source code has passed in the review process.
  * @return the default value is {@link Stage#New}.
  */
public Stage stage() default New;
 
/**
  * The String date of when this code was last reviewed, which is not a Date
  * object because that is an illegal type in annotation parameters.
  * @return the date this code was reviewed.
  */
public String date();

/**
  * The names of the supervisors or members of the development team who have
  * reviewed this code.
  * @return the names or initials of the team members who have reviewed this
  * code.
  */
public String[] reviewers();
}

January 11, 2007 in Tech Notes | Permalink | Comments (1)

Java Web App Debugger

An new tool for Java EE developers, called JWAD, is available from Downloads.com at http://www.download.com/JWAD-Java-Web-App-Debugger-/3000-2417_4-10617972.html?tag=emailThis

My friend Barney Marispini has done a great job with this tool, which shows you all of the values available in any scope in a web request. The UI is very slick and installation is easy. The download size is small (46k). I would highly recommend trying this tool out.

January 02, 2007 in Tech Notes | Permalink | Comments (0)

Ant 1.7 Available

The new, 1.7 version of the Apache Ant Java build automation tool was released Tuesday with a new resource framework. This allows standard Ant functions to understand and deal with .zip files, .tar files, directory structures and other common UNIX items. Also added to version 1.7 is preliminary support for some Java SE 6 functions. Ant is open source and available under the Apache Software License, and can be downloaded at http://ant.apache.org/bindownload.cgi.

December 22, 2006 in Tech Notes | Permalink | Comments (0)

VarArgs as parameters to public EJB Methods on BEA WebLogic 9.2

WebLogic's EJB 9.2 compiler rejects public method definitions using varargs. It does so in a very weird way: it complains that "transient" is not allowed as a method modifier, which of course it isn't.

It is possible that there is something that XDoclet 1.2.3 is generating that confuses WebLogic, but that was not the case with parameterized types in WebLogic 9.0 or 9.1, so my money is on WebLogic as the culprit.

I wrote this method in my EJB:

public void recordRecalculateMarketPricingEvent(

RecalculateMarketPricingEvent event, AuditRecordAction...actions)

And this was the result at deploy time (XDoclet didn't mind it):

<Oct 12, 2006 2:46:19 PM MST> <Debug> <EjbCompilation> <000000> <[EJBCompiler] Compiling EJB sources>

/tmp/appcgen_pricing.ear/appcgen_pricing-ejb.jar/com/dte/pricing/ejb/AuditService_ibl70p_Intf.java:21: modifier transient not allowed here

public transient void recordRecalculateMarketPricingEvent(com.dte.pricing.events.RecalculateMarketPricingEvent arg0, com.dte.pricing.events.AuditRecordAction[] arg1)

Looking at the source that is indeed what WebLogic generated for the public Local Interface:

/**


* This code was automatically generated at 3:07:24 PM on Oct 12, 2006
* by weblogic.ejb.container.ejbc.Ejb2Rmi -- do not edit.
*
* @version WebLogic Server 9.2 Fri Jun 23 20:47:26 EDT 2006 783464
* @author Copyright (c) 2006 by BEA Systems, Inc. All Rights Reserved.
*/

package com.dte.pricing.ejb;

import weblogic.ejb.container.interfaces.WLEnterpriseBean;
public interface AuditService_ibl70p_Intf
extends WLEnterpriseBean
{


public void ejbActivate();
public void ejbCreate();
public void ejbPassivate();
public void ejbRemove();
public transient void recordRecalculateMarketPricingEvent(com.dte.pricing.events.RecalculateMarketPricingEvent arg0, com.dte.pricing.events.AuditRecordAction[] arg1)
throws com.dte.shared.persist.PersistenceException;

public void setSessionContext(javax.ejb.SessionContext arg0);

Somehow WebLogic knows that it is a varargs method and translates it to an array. But for some bizarre reason, it puts transient in front of my method definition, and the AppC compiler rejects it.

Changing my method to this is my only current workaround:

public void recordRecalculateMarketPricingEvent(

RecalculateMarketPricingEvent event, AuditRecordAction[] actions)

WebLogic has no problem with private vararg methods however, presumably because it doesn't touch them. Which means JRockit has no problem with it. This works:

private void printArgs(AuditRecordAction...actions)

This is frustrating. With WebLogic 9.0 and even in 9.1 defining methods with parameterized types as arguments in an EJB would get rejected by the compiler. That is, this would not work:

public void work(List<Product> products)

But this would work:

public void work(List products)

That was finally fixed in WebLogic 9.2. And what was weird about that issue was that you could return parameterized types from a public EJB method in WebLogic 9.0 and 9.1. So this worked fine:

public List<Product> work(String something)

Is the idea that we get more or less one implementation of a new feature in Java 5 with every release of WL? I wonder if we get covariant returns...

October 12, 2006 in Tech Notes | Permalink | Comments (0)

»
My Photo

Recent Posts

  • My Upcoming Speaking Schedule
  • Service Design Review Checklist for SOA Governance
  • 10 Ways to Beat Writer's Block
  • Moving Main Blog to Cassandra Guide
  • A Literary Life: Our Book Reorganization Project
  • Talk Abstracts for Business & Technology Summit 2009 in Bangalore, India
  • 97 Things Every Software Architect Should Know on Kindle, iPhone, in Japanese
  • Using SOAP Faults and Exceptions in Java JAX-WS Web Services
  • Recipe for the Perfect Margarita
  • Towards a Rhizomatic Software Architecture
Subscribe to this blog's feed

Reading

  • Robert Hanmer: Patterns for Fault Tolerant Software (Wiley Software Patterns Series)

    Robert Hanmer: Patterns for Fault Tolerant Software (Wiley Software Patterns Series)

  • Kerrie Holley: 100 SOA Questions: Asked and Answered

    Kerrie Holley: 100 SOA Questions: Asked and Answered

  • Haralambos Marmanis: Algorithms of the Intelligent Web

    Haralambos Marmanis: Algorithms of the Intelligent Web

  • John Hebeler: Semantic Web Programming

    John Hebeler: Semantic Web Programming

  • Steven Bird: Natural Language Processing with Python

    Steven Bird: Natural Language Processing with Python

Categories

  • Articles (9)
  • Books (2)
  • Food and Drink (1)
  • Recipes (9)
  • Tech Notes (26)
See More

July 2010

Sun Mon Tue Wed Thu Fri Sat
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31

Twitter Updates

    follow me on Twitter