Removed JAX-RPC support
This commit is contained in:
@@ -51,11 +51,6 @@
|
||||
<classname>BurlapServiceExporter</classname>.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><emphasis>JAX-RPC</emphasis>. Spring provides remoting support
|
||||
for web services via JAX-RPC (J2EE 1.4's web service API).</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><emphasis>JAX-WS</emphasis>. Spring provides remoting support
|
||||
for web services via JAX-WS (the successor of JAX-RPC, as introduced
|
||||
@@ -501,14 +496,6 @@ public class AccountServiceImpl implements AccountService {
|
||||
APIs:</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>Exposing web services using JAX-RPC</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Accessing web services using JAX-RPC</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Exposing web services using JAX-WS</para>
|
||||
</listitem>
|
||||
@@ -518,285 +505,13 @@ public class AccountServiceImpl implements AccountService {
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<note>
|
||||
<para>Why two standard Java web services APIs?</para>
|
||||
|
||||
<para>JAX-RPC 1.1 is the standard web service API in J2EE 1.4. As its
|
||||
name indicates, it focuses on on RPC bindings, which became less and
|
||||
less popular in the past couple of years. As a consequence, it has been
|
||||
superseded by JAX-WS 2.0 in Java EE 5, being more flexible in terms of
|
||||
bindings but also being heavily annotation-based. JAX-WS 2.1 is also
|
||||
included in Java 6 (or more specifically, in Sun's JDK 1.6.0_04 and
|
||||
above; previous Sun JDK 1.6.0 releases included JAX-WS 2.0), integrated
|
||||
with the JDK's built-in HTTP server.</para>
|
||||
|
||||
<para>Spring can work with both standard Java web services APIs. On Java
|
||||
EE 5 / Java 6, the obvious choice is JAX-WS. On J2EE 1.4 environments
|
||||
that run on Java 5, you might have the option to plug in a JAX-WS
|
||||
provider; check your Java EE server's documentation.</para>
|
||||
</note>
|
||||
|
||||
<para>In addition to stock support for JAX-RPC and JAX-WS in Spring Core,
|
||||
<para>In addition to stock support for JAX-WS in Spring Core,
|
||||
the Spring portfolio also features <link
|
||||
xl:href="http://www.springframework.org/spring-ws">Spring Web
|
||||
Services</link>, a solution for contract-first, document-driven web
|
||||
services - highly recommended for building modern, future-proof web
|
||||
services.</para>
|
||||
|
||||
<section xml:id="remoting-web-services-jaxrpc-export">
|
||||
<title>Exposing servlet-based web services using JAX-RPC</title>
|
||||
|
||||
<para>Spring provides a convenience base class for JAX-RPC servlet
|
||||
endpoint implementations -
|
||||
<classname>ServletEndpointSupport</classname>. To expose our
|
||||
<interfacename>AccountService</interfacename> we extend Spring's
|
||||
<classname>ServletEndpointSupport</classname> class and implement our
|
||||
business logic here, usually delegating the call to the business
|
||||
layer.</para>
|
||||
|
||||
<programlisting language="java"><lineannotation>/**
|
||||
* JAX-RPC compliant RemoteAccountService implementation that simply delegates
|
||||
* to the AccountService implementation in the root web application context.
|
||||
*
|
||||
* This wrapper class is necessary because JAX-RPC requires working with dedicated
|
||||
* endpoint classes. If an existing service needs to be exported, a wrapper that
|
||||
* extends ServletEndpointSupport for simple application context access is
|
||||
* the simplest JAX-RPC compliant way.
|
||||
*
|
||||
* This is the class registered with the server-side JAX-RPC implementation.
|
||||
* In the case of Axis, this happens in "server-config.wsdd" respectively via
|
||||
* deployment calls. The web service engine manages the lifecycle of instances
|
||||
* of this class: A Spring application context can just be accessed here.
|
||||
*/</lineannotation>import org.springframework.remoting.jaxrpc.ServletEndpointSupport;
|
||||
|
||||
public class AccountServiceEndpoint extends ServletEndpointSupport implements RemoteAccountService {
|
||||
|
||||
private AccountService biz;
|
||||
|
||||
protected void onInit() {
|
||||
this.biz = (AccountService) getWebApplicationContext().getBean("accountService");
|
||||
}
|
||||
|
||||
public void insertAccount(Account acc) throws RemoteException {
|
||||
biz.insertAccount(acc);
|
||||
}
|
||||
|
||||
public Account[] getAccounts(String name) throws RemoteException {
|
||||
return biz.getAccounts(name);
|
||||
}
|
||||
}</programlisting>
|
||||
|
||||
<para>Our <classname>AccountServletEndpoint</classname> needs to run in
|
||||
the same web application as the Spring context to allow for access to
|
||||
Spring's facilities. In case of Axis, copy the
|
||||
<classname>AxisServlet</classname> definition into your
|
||||
<filename>'web.xml'</filename>, and set up the endpoint in
|
||||
<filename>'server-config.wsdd'</filename> (or use the deploy tool). See
|
||||
the sample application JPetStore where the
|
||||
<interfacename>OrderService</interfacename> is exposed as a web service
|
||||
using Axis.</para>
|
||||
</section>
|
||||
|
||||
<section xml:id="remoting-web-services-jaxrpc-access">
|
||||
<title>Accessing web services using JAX-RPC</title>
|
||||
|
||||
<para>Spring provides two factory beans to create JAX-RPC web service
|
||||
proxies, namely <classname>LocalJaxRpcServiceFactoryBean</classname> and
|
||||
<classname>JaxRpcPortProxyFactoryBean</classname>. The former can only
|
||||
return a JAX-RPC service class for us to work with. The latter is the
|
||||
full-fledged version that can return a proxy that implements our
|
||||
business service interface. In this example we use the latter to create
|
||||
a proxy for the <interfacename>AccountService</interfacename> endpoint
|
||||
we exposed in the previous section. You will see that Spring has great
|
||||
support for web services requiring little coding efforts - most of the
|
||||
setup is done in the Spring configuration file as usual:</para>
|
||||
|
||||
<programlisting language="xml"><bean id="accountWebService" class="org.springframework.remoting.jaxrpc.JaxRpcPortProxyFactoryBean">
|
||||
<property name="serviceInterface" value="example.RemoteAccountService"/>
|
||||
<property name="wsdlDocumentUrl" value="http://localhost:8080/account/services/accountService?WSDL"/>
|
||||
<property name="namespaceUri" value="http://localhost:8080/account/services/accountService"/>
|
||||
<property name="serviceName" value="AccountService"/>
|
||||
<property name="portName" value="AccountPort"/>
|
||||
</bean></programlisting>
|
||||
|
||||
<para>Where <literal>serviceInterface</literal> is our remote business
|
||||
interface the clients will use. <literal>wsdlDocumentUrl</literal> is
|
||||
the URL for the WSDL file. Spring needs this at startup time to create
|
||||
the JAX-RPC Service. <literal>namespaceUri</literal> corresponds to the
|
||||
targetNamespace in the .wsdl file. <literal>serviceName</literal>
|
||||
corresponds to the service name in the .wsdl file.
|
||||
<literal>portName</literal> corresponds to the port name in the .wsdl
|
||||
file.</para>
|
||||
|
||||
<para>Accessing the web service is now very easy as we have a bean
|
||||
factory for it that will expose it as
|
||||
<literal>RemoteAccountService</literal> interface. We can wire this up
|
||||
in Spring:</para>
|
||||
|
||||
<programlisting language="xml"><bean id="client" class="example.AccountClientImpl">
|
||||
...
|
||||
<property name="service" ref="accountWebService"/>
|
||||
</bean></programlisting>
|
||||
|
||||
<para>From the client code we can access the web service just as if it
|
||||
was a normal class, except that it throws
|
||||
<exceptionname>RemoteException</exceptionname>.</para>
|
||||
|
||||
<programlisting language="java">public class AccountClientImpl {
|
||||
|
||||
private RemoteAccountService service;
|
||||
|
||||
public void setService(RemoteAccountService service) {
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
public void foo() {
|
||||
try {
|
||||
service.insertAccount(...);
|
||||
}
|
||||
catch (RemoteException ex) {
|
||||
<lineannotation>// ouch</lineannotation>
|
||||
}
|
||||
}
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
<para>We can get rid of the checked
|
||||
<exceptionname>RemoteException</exceptionname> since Spring supports
|
||||
automatic conversion to its corresponding unchecked
|
||||
<exceptionname>RemoteException</exceptionname>. This requires that we
|
||||
provide a non-RMI interface also. Our configuration is now:</para>
|
||||
|
||||
<programlisting language="xml"><bean id="accountWebService" class="org.springframework.remoting.jaxrpc.JaxRpcPortProxyFactoryBean">
|
||||
<property name="serviceInterface" value="example.AccountService"/>
|
||||
<property name="portInterface" value="example.RemoteAccountService"/>
|
||||
...
|
||||
</bean></programlisting>
|
||||
|
||||
<para>Where <literal>serviceInterface</literal> is changed to our non
|
||||
RMI interface. Our RMI interface is now defined using the property
|
||||
<literal>portInterface</literal>. Our client code can now avoid handling
|
||||
<exceptionname>java.rmi.RemoteException</exceptionname>:</para>
|
||||
|
||||
<programlisting language="java">public class AccountClientImpl {
|
||||
|
||||
private AccountService service;
|
||||
|
||||
public void setService(AccountService service) {
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
public void foo() {
|
||||
service.insertAccount(...);
|
||||
}
|
||||
}</programlisting>
|
||||
|
||||
<para>Note that you can also drop the "portInterface" part and specify a
|
||||
plain business interface as "serviceInterface". In this case,
|
||||
<classname>JaxRpcPortProxyFactoryBean</classname> will automatically
|
||||
switch to the JAX-RPC "Dynamic Invocation Interface", performing dynamic
|
||||
invocations without a fixed port stub. The advantage is that you don't
|
||||
even need to have an RMI-compliant Java port interface around (e.g. in
|
||||
case of a non-Java target web service); all you need is a matching
|
||||
business interface. Check out
|
||||
<classname>JaxRpcPortProxyFactoryBean</classname>'s javadoc for details
|
||||
on the runtime implications.</para>
|
||||
</section>
|
||||
|
||||
<section xml:id="remoting-web-services-jaxrpc-mapping-registration">
|
||||
<title>Registering JAX-RPC Bean Mappings</title>
|
||||
|
||||
<para>To transfer complex objects over the wire such as
|
||||
<classname>Account</classname> we must register bean mappings on the
|
||||
client side.</para>
|
||||
|
||||
<note>
|
||||
<para>On the server side using Axis registering bean mappings is
|
||||
usually done in the <filename>'server-config.wsdd'</filename>
|
||||
file.</para>
|
||||
</note>
|
||||
|
||||
<para>We will use Axis to register bean mappings on the client side. To
|
||||
do this we need to register the bean mappings programmatically:</para>
|
||||
|
||||
<programlisting language="java">public class AxisPortProxyFactoryBean extends JaxRpcPortProxyFactoryBean {
|
||||
|
||||
protected void postProcessJaxRpcService(Service service) {
|
||||
TypeMappingRegistry registry = service.getTypeMappingRegistry();
|
||||
TypeMapping mapping = registry.createTypeMapping();
|
||||
registerBeanMapping(mapping, Account.class, "Account");
|
||||
registry.register("http://schemas.xmlsoap.org/soap/encoding/", mapping);
|
||||
}
|
||||
|
||||
protected void registerBeanMapping(TypeMapping mapping, Class type, String name) {
|
||||
QName qName = new QName("http://localhost:8080/account/services/accountService", name);
|
||||
mapping.register(type, qName,
|
||||
new BeanSerializerFactory(type, qName),
|
||||
new BeanDeserializerFactory(type, qName));
|
||||
}
|
||||
}</programlisting>
|
||||
</section>
|
||||
|
||||
<section xml:id="remoting-web-services-jaxrpc-handler-registration">
|
||||
<title>Registering your own JAX-RPC Handler</title>
|
||||
|
||||
<para>In this section we will register our own
|
||||
<interfacename>javax.rpc.xml.handler.Handler</interfacename> to the web
|
||||
service proxy where we can do custom code before the SOAP message is
|
||||
sent over the wire. The <interfacename>Handler</interfacename> is a
|
||||
callback interface. There is a convenience base class provided in
|
||||
<filename class="libraryfile">jaxrpc.jar</filename>, namely
|
||||
<classname>javax.rpc.xml.handler.GenericHandler</classname> that we will
|
||||
extend:</para>
|
||||
|
||||
<programlisting language="java">public class AccountHandler extends GenericHandler {
|
||||
|
||||
public QName[] getHeaders() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean handleRequest(MessageContext context) {
|
||||
SOAPMessageContext smc = (SOAPMessageContext) context;
|
||||
SOAPMessage msg = smc.getMessage();
|
||||
try {
|
||||
SOAPEnvelope envelope = msg.getSOAPPart().getEnvelope();
|
||||
SOAPHeader header = envelope.getHeader();
|
||||
...
|
||||
}
|
||||
catch (SOAPException ex) {
|
||||
throw new JAXRPCException(ex);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}</programlisting>
|
||||
|
||||
<para>What we need to do now is to register our AccountHandler to
|
||||
JAX-RPC Service so it would invoke
|
||||
<methodname>handleRequest(..)</methodname> before the message is sent
|
||||
over the wire. Spring has at this time of writing no declarative support
|
||||
for registering handlers, so we must use the programmatic approach.
|
||||
However Spring has made it very easy for us to do this as we can
|
||||
override the <methodname>postProcessJaxRpcService(..)</methodname>
|
||||
method that is designed for this:</para>
|
||||
|
||||
<programlisting language="java">public class AccountHandlerJaxRpcPortProxyFactoryBean extends JaxRpcPortProxyFactoryBean {
|
||||
|
||||
protected void postProcessJaxRpcService(Service service) {
|
||||
QName port = new QName(this.getNamespaceUri(), this.getPortName());
|
||||
List list = service.getHandlerRegistry().getHandlerChain(port);
|
||||
list.add(new HandlerInfo(AccountHandler.class, null, null));
|
||||
logger.info("Registered JAX-RPC AccountHandler on port " + port);
|
||||
}
|
||||
}</programlisting>
|
||||
|
||||
<para>The last thing we must remember to do is to change the Spring
|
||||
configuration to use our factory bean:</para>
|
||||
|
||||
<programlisting language="xml"><bean id="accountWebService" class="example.AccountHandlerJaxRpcPortProxyFactoryBean">
|
||||
...
|
||||
</bean></programlisting>
|
||||
</section>
|
||||
|
||||
<section xml:id="remoting-web-services-jaxws-export-servlet">
|
||||
<title>Exposing servlet-based web services using JAX-WS</title>
|
||||
|
||||
@@ -937,9 +652,8 @@ public class AccountServiceEndpoint {
|
||||
<section xml:id="remoting-web-services-jaxws-access">
|
||||
<title>Accessing web services using JAX-WS</title>
|
||||
|
||||
<para>Analogous to the JAX-RPC support, Spring provides two factory
|
||||
beans to create JAX-WS web service proxies, namely
|
||||
<classname>LocalJaxWsServiceFactoryBean</classname> and
|
||||
<para>Spring provides two factory beans to create JAX-WS web service
|
||||
proxies, namely <classname>LocalJaxWsServiceFactoryBean</classname> and
|
||||
<classname>JaxWsPortProxyFactoryBean</classname>. The former can only
|
||||
return a JAX-WS service class for us to work with. The latter is the
|
||||
full-fledged version that can return a proxy that implements our
|
||||
|
||||
Reference in New Issue
Block a user