The soaprest project is a framework for developing web service endpoints that accept both SOAP and REST invocations. One of the design problems in web services is that one must decide whether to use SOAP or REST. Existing frameworks limit a particular endpoint to be either SOAP or REST. A soaprest endpoint is specified as a SOAP web service using WSDL, but will also accept REST invocations, and will respond according to how a request was invoked. This gives one the advantages of both SOAP and REST in a single web service.
This is an experimental project, and it does not support all of the features of Java Web Services. It also maps from SOAP to REST, not the other way around, so only a few of the REST parameter styles are used. The mapping from SOAP to REST is the following:
The SOAP web service is relatively general, but a few restrictions are necessary for the mapping to REST to be possible:
@WebService(name = "Plastering", targetNamespace = "http://xyz.org") public class PlasteringImpl implements PlasteringInterface {Some annotations can be omitted, but one should not depend on this behavior. More information about the annotations is shown below. The soaprest code tries to find default values, but they might not be the same ones that JWS would use.
The web service may be deployed either as a stand-alone service or as a component in a servlet container. Note that the provider must be deployed, not the implementation class. The container can be any servlet container. It is not necessary to have a container that supports web services. The endpoint (provider) class must have the following properties:
getInitParameter
method after the endpoint
has been deployed. This is normally done by overriding the init()
method.
The following are the annotations used by the soaprest package:
Location of annotation | Annotation | Discussion |
---|---|---|
The endpoint class | WebServiceProvider | Required for stand-alone deployment |
ServiceMode | Required for stand-alone deployment and must have value Service.Mode.PAYLOAD | |
SoapRestProvider | Required for servlet container deployment | |
The implementation class | WebService | Required and should specify the name of the web service. |
Doc | Optional documentation for the REST API. | |
An operation (web method) | WebMethod | Required and may specify an operationName which overrides the name of the method |
RequestWrapper | Required for specifying the className | |
ResponseWrapper | Required for specifying the className | |
Oneway | Optional specification of a web service operation that does not return. A one-way operation may only be RESTfully invoked using the HTTP PUT and DELETE methods. A two-way operation may only be RESTfully invoked using the HTTP GET and POST methods. SOAP requests are invoked with the HTTP POST method whether they are one-way or two-way. | |
Doc | Optional documentation for the REST API. | |
HTTPMethods | Optional restriction on the HTTP methods that may be used on the operation. See the discussion of the Oneway annotation for the defaults. Note that one can restrict the defaults, but one cannot remove any of the default restrictions. | |
The request wrapper of a web method | XmlType | Required for specifying the propOrder |
The response wrapper of a web method | XmlType | Required for specifying the propOrder. There must be exactly one property in a response wrapper. |
A parameter of a web method | WebParam | Required for specifying the parameter name |
WebParam.mode | Must be IN | |
DefaultValue | Optional specification of the default value for a parameter convertible from a string | |
Doc | Optional documentation for the REST API. The title is used to explain the parameter in the HTTP signature. |
Conversions are a large topic, but one special case is provided by the soaprest package. A class is convertible from String if the class has a constructor with a single String parameter and does not throw any exceptions. Conversion to String uses the toString method. Primitive types are also convertible from String by means of autoboxing and unboxing. However, primitive types do not accept null arguments.
When an operation is invoked with a GET, the parameters will automatically be converted to the target types by the soaprest package. The same is true for primitive types. When an operation that has non-primitive parameters that are convertible from String is invoked with a POST (for example, when it is invoked using SOAP), then one must modify the request wrapper classes that are generated by wsimport so that the parameters have the target types. For a return value, one must modify the response wrapper classes in a similar way.
The modification of the wrapper classes can be specified using JAXB annotations in the XSD part of the WSDL. Here is how this is done:
<xsd:simpleType name="ConvertibleType"> <xsd:annotation> <xsd:appinfo> <jaxb:javaType name="org.project.MyConveribleType"/> </xsd:appinfo> </xsd:annotation> <xsd:restriction base="xsd:string"/> </xsd:simpleType>The annotation tells wsimport (or more precisely, xjc) to use
org.project.MyConveribleType
instead of String in the generated
code.
One would think that the classes URL and URI would be convertible from String, but their constructors throw an exception if the argument is not correctly formed. However, if one modifies the generated code manually, then the web service works fine.
As with any experimental project,
Copyright (c) 2012 Ken Baclawski. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
THIS SOFTWARE IS PROVIDED BY KEN BACLAWSKI ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEN BACLAWSKI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.