Network Deployment (Distributed operating systems), v8.0 > Develop and deploying applications > Develop SCA composites > Develop SCA applications
Use business exceptions with SCA interfaces
We can implement exceptions for remotable interfaces in the Service Component Architecture (SCA) environment to provide additional flow of control for error conditions to meet the needs of your business application.
To develop SCA service implementations, you can use either a top-down development approach starting with an existing Web Services Description Language (WSDL) file or you can use a bottom-up development approach starting from an existing Java interface or implementation. When using either the top-down or bottom-up development methodologies, you can use tools to map business exceptions on remotable interfaces.
In order to achieve the SOA goal of providing an interoperable platform that is both language and technology neutral, the SCA runtime environment takes an XML-centric view of interfaces and data. When working with Java code, the Java API for XML-Based Web Services (JAX-WS) standard is used to define the mapping between Java code and the XML-based WSDL file. This mapping also includes the Java programming model with respect to exceptions. Exceptions for remotable interfaces in the SCA environment is defined by the JAX-WS specification. This topic describes the best practices for using business exceptions with SCA interfaces.
Differences between business exceptions and fault beans
To better understand the implications of implementing business exceptions in an SCA environment, it is helpful to understand differences between an exception and a fault bean.
The JAX-WS specification distinguishes between a checked exception and the fault bean that it wrappers. However, this distinction might not be clear because a single class can serve the checked exception and the fault bean functions, especially when you use the bottom-up approach of developing an SCA service starting with a Java interface. When you use the top-down development approach of developing an SCA service starting with a WSDL file, section 2.5 of the JAX-WS specification describes the wrapper pattern for how the fault message maps to a Java checked exception that wraps a fault bean. The fault bean maps to the fault element and in SCA environments, the mapping is defined by Java Architecture for XML Binding (JAXB) data binding. The fault bean represents the cross-platform view of the fault message data and includes a schema description. We can use the Java exception within the Java runtime environment and as part of the Java programming model. However, the exception is not part of the interoperable data representation.
When developing SCA services using the bottom-up approach, the distinction between an exception, the fault bean, and the mapping from Java to WSDL or XSD schema is clear if you follow the wrapper pattern described in section 2.5 of the JAX-WS specification. If we have existing Java exceptions, use the standard mapping defined in section 3.7 of the JAX-WS specification for service specific exceptions. In SCA environments, these service specific exceptions are referred to as business exceptions. The mapping for the business exceptions is different than the mapping described in section 2.5 of the JAX-WS specification. Because this wrapper pattern only applies for certain exceptions, this approach has limitations when using the bottom-up development approach. The possible limitations of using the wrapper pattern to implement error handling when using bottom-up development of SCA applications provides additional reasons to consider the advantages of the best practice of top-down development of SCA applications.
Top-down development, starting from a WSDL operation with fault messages
It is a best practice to use the top-down methodology to develop SCA service implementations because this approach leverages the capabilities of the XML interface description and provides a greater ease in interoperability across platforms, bindings, and programming languages. A WSDL operation can be defined, along with one or more fault messages, provided each fault message is defined in terms of a fault element. When the wsimport command-line tool is used to generate Java code the tool generates Java exception code that wraps a fault element in the format specified by the Java API for JAX-WS specification, section 2.5.
Bottom-up development, starting from a Java operation with throws clause
Bottom-up development of SCA services occurs when you start with existing Java code. Using this development approach, do not design a remotable interface that might cause a technology exception such as java.sql.SQLException. This exception is more appropriate for a local interface rather than a coarse-grained remotable interface.
Procedure
- For top-down development of SCA applications, implement a wrapper pattern for business exceptions.
The wrapper pattern is based on section 2.5 of the JAX-WS specification.
- Obtain your WSDL file; for example:
<wsdl:types> ... <element name="errorCode" type="xsd:int"/> ... </wsdl:types> <wsdl:message name="BadInputMsg"> <wsdl:part element="tns:errorCode" name="parameters"/> </wsdl:message> <wsdl:portType name="GuessAndGreet"> <wsdl:operation name="sendGuessAndName"> <wsdl:input.../> <wsdl:fault message="tns:BadInputMsg" name="BadInputMsg"/>- Generate the Java artifacts using the wsimport tool. We can define the fault according to section 2.5 of the JAX-WS specification; for example:
Interface public Person sendGuessAndName(...) throws BadInputMsg;- Wrap an exception in a fault; for example:
import javax.xml.ws.WebFault; @WebFault(name = "errorCode", targetNamespace = "....") public class BadInputMsg extends Exception { private int faultInfo; public BadInputMsg(String message, int faultInfo) { super(message); this.faultInfo = faultInfo; } public BadInputMsg(String message, int faultInfo, Throwable cause) { super(message, cause); this.faultInfo = faultInfo; } public int getFaultInfo() { return faultInfo; } }
- For bottom-up development of SCA applications, implement or convert the exception to follow the wrapper pattern or use the default mapping for of a JAX-WS service specific exception.
If we have a Java business exception, the complexity of this scenario increases, especially if your exception wraps fault data. For example, the exception wraps data such as an error code or an object that it needs to provide to the client that receives the exception. In this scenario, there are two options:
- Convert the Java business exception to follow the wrapper pattern as described in section 2.5 of the JAX-WS specification.
Using the wrapper pattern for the exception enables the exception to map easily from the WSDL to Java code format and then from the Java code to WSDL format. If you modify the exception to follow the wrapper pattern, you can use the wsgen tool to convert from Java code to WSDL and later use the wsimport tool to convert from WSDL to Java code, the exception is similar to the one that you modified.
To achieve this end goal, perform the following steps:
- Add constructors that take the fault bean as input parameters.
- Implement a public getFaultInfo() method that returns the fault bean.
- Add the @javax.xml.ws.WebFault annotation. See the example that wraps an exception in a fault.
- Use the default mapping of a JAX-WS service specific exception or business exception as described in section 3.7 of the JAX-WS specification.
If you use the wsgen command-line tool to generate the WSDL, the tool uses this pattern for business exceptions. If you do not generate the WSDL file before deployment, the application server runtime environment implicitly generates the business exception using this pattern.
Use this option when you:
- cannot change the exception class to follow the JAX-WS wrapper pattern.
- rely on the runtime environment to map the Java code into WSDL such as declaring a <binding.ws> binding on a service that is deployed without a WSDL file.
Either of these options work without any additional complexity as long as the exception does not contain fault data.
For exceptions with fault data, the data is handled correctly for each field that contains a public getter or setter method. However, data is lost without a getter or setter pair. In other words, serialize or deserialize the exception by viewing it as a Java code.
When using this second option, the following items are important:
- The supported fault pattern is not easily determined. One exception with fault data and also with the getter and setter methods is that some are handled correctly while others are not. Running the wsgen tool at development time generates the schema based on the exception getter methods without assuring that the corresponding setter methods exist in order to populate the exception during unmarshalling.
- If you run wsimport tool against the generated WSDL, you get a different exception class. Your client and service programming model are different which might confuse the Java programmer. However, this generated Java exception follows the pattern described in the JAX-WS specification in section 2.5. You might need to add customization for JAXB data binding in order to generate the client. The results can produce exception names similar to MyException_Exception.
- Although the service-specific exception pattern is described in section 3.7 of the JAX-WS specification, not all details for the pattern are specified. Other software implementing JAX-WS might implement the pattern differently. This is not critical, since the WSDL file is interoperable across platforms.
Example
The following examples illustrates using the bottom-up development of SCA applications and using the business exception mapping as described in section 3.7 of the JAX-WS specification.
Example 1: No fault
The string message is the fault in this example, and it is serialized and deserialized successfully.
public class RealSimpleException extends Exception { public RealSimpleException(String message) { super(message); } public RealSimpleException(String message, Throwable cause) { super(message, cause); } }Example 2: Exception as JavaBeans
This example works correctly because the string userdata fault has associated public getter and setter methods. The string message is also handled correctly.
public class TestException extends Exception { private String userdata; public TestException(String message) { super(message); } public TestException(String message, String userdata) { super(message); this.userdata = userdata; } public String getUserdata() { return userdata; } public void setUserdata(String userdata) { this.userdata = userdata; } }Example 3: Exception does not follow pattern
This example does not work correctly because the errorCode fault data does not have a setter method. The SCA runtime is not able to correctly determine how to populate the exception with this fault data. The exception occurs, but it is displayed with data loss.
package java.sql; public class SQLException extends Exception ... { ... public SQLException(String theReason, String theSQLState, int theErrorCode) ... public int getErrorCode() }
What to do next
Increase portability of your exception classes in top-down development
One issue that you might encounter with Java exceptions generated from WSDL in the top-down manner is that the fault bean might not be Java-serializable. In other words, the fault bean might not implement java.io.Serializable. This does not present a problem if the bindings that the application uses are in XML wireformat because, in that scenario, XML serialization is used instead of Java serialization. However, XML serialization limits the usefulness of your exception class. Therefore, it might not be suitable to use with SCA binding configurations using a wireformat with Java serialization, or in other contexts in which Java serialization is used to serialize and deserialize an exception.
To avoid this limitation, annotate your schema definition for the fault element type with a JAXB customization designed for this purpose. When this customization is present, the JAXB type that is generated, that corresponds to the fault bean, is marked as implementing the java.io.Serializable interface, and is therefore Java serializable, in addition to being serializable to XML, because the class is also still a conforming JAXB type.
Example:
<schema targetNamespace="http://com.mycompany/banking/" jaxb:version="2.0" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns="http://www.w3.org/2001/XMLSchema"> <annotation> <appinfo> <jaxb:globalBindings> <jaxb:serializable uid="1"/> </jaxb:globalBindings> </appinfo> </annotation> <!-- Continue with the rest of the schema definition--> </schema>SCA programming tip for binding neutrality
The JAX-WS defined mapping between exceptions in Java and an XML wireformat relies on the use of the fault bean to pass back data from the service provider throwing the exception to the client that is catching it. Normal Java-centric mechanisms, such as exception chaining, are not preserved in mapping between the Java application and the wire. Therefore, the best way to write application code that can be used across binding configurations using either of a Java serialization wireformat or an XML wireformat is to rely exclusively on the fault bean for communicating useful application level data relating to the exception.
Even though using a chained exception across a binding that uses a Java-serialization based wireformat works fine, using a chained exception across a binding using XML wireformat might not work. Therefore relying on a chained exception would not be a recommended practice in an SCA environment, because SCA strives to provide a binding-neutral programming model.
Develop SCA services from existing WSDL files
Develop SCA services with existing Java code
Develop SCA service clients
Specify bindings in an SCA environment
wsimport command for JAX-WS applications
Related
Service Component Architecture specifications and APIs