Announcement Announcement Module
Collapse
No announcement yet.
Automatic network failure recovery with Axis & JaxRpcPortClientInterceptor Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Automatic network failure recovery with Axis & JaxRpcPortClientInterceptor

    The Spring framework includes a very handy class in the form of JaxRpcPortClientInterceptor as part of the Remoting package. This class allows you to treat web services just like any other dependency - configure, create and inject them in your application context XML file. This is quite clever in that you can write code that works against a Java interface and doesn't care about the underlying remoting protocol used.

    The JaxRpcPortClientInterceptor class has a "lookupServiceOnStartup" property which lets you defer the WSDL fetching and initialization until the first request is made. This can help you if the server hosting the web service is not up at the time when the port interceptor is being initialized, however it doesn't help if the web service host disappears afterwards or does not become available until after a call is made. It would appear that Apache Axis (which is the actual JAX-RPC implementation used) gets confused quite easily by network failures and so it helps if you re-create the JaxRpcPortClientInterceptor whenever such a failure is detected. However, if you wanted to keep the benefits of IoC, handling these failures could result in a complicated tangle of BeanFactoryAware factories and exception handling code - not exactly what we want after we've seen just how elegant SOAP access can be with a little Spring magic. I found that in some cases I had to redeploy my application after the web service host disappeared for a short period of time - this is unacceptable in a production environment.

    The following code uses Spring's own AOP framework to implement a form of failure recovery completely transparently to existing code. This demonstrates the combined power of IoC and AOP quite well - they allow us to modify behaviour without touching the existing code which was not explicitly designed for pure OOP extensibility (see the Open-Closed Principle about that).

    The following XML fragment contains both the original "pure Spring" approach to configuring web service access using Axis:

    Code:
    <beans>
    
        <bean id="plainWebservice" class="org.springframework.remoting.jaxrpc.JaxRpcPortProxyFactoryBean">
            <property name="serviceInterface" value="com.example.service.IService"/>
            <property name="namespaceUri" value="..."/>
            <property name="portName" value="..."/>
            <property name="wsdlDocumentUrl" value="..."/>
        </bean>
    
        <bean id="myBusinessComponent" class="com.example.Component">
            <property name="bizService" ref="plainWebservice"/>
        </bean>
    
    </beans>
    And here is a more reliable method using AOP and my custom TargetSource:

    Code:
    <beans>
    
        <bean id="webservicePort" class="org.springframework.remoting.jaxrpc.JaxRpcPortClientInterceptor" singleton="false">
            <property name="serviceInterface" value="com.example.service.IService"/>
            <property name="namespaceUri" value="..."/>
            <property name="portName" value="..."/>
            <property name="wsdlDocumentUrl" value="..."/>
        </bean>
    
        <bean id="reliableWebservice" class="org.springframework.aop.framework.ProxyFactoryBean">
            <property name="targetSource">
                <bean class="za.net.kay.JaxRpcPortTargetSource">
                    <property name="targetBeanName" value="webservicePort"/>
                </bean>
            </property>
        </bean>
    
        <bean id="myBusinessComponent" class="com.example.Component">
            <property name="bizService" ref="reliableWebservice"/>
        </bean>
    
    </beans>
    Notice how our business component still knows nothing about looking up the web service - we're getting the full benefit of IoC with component wiring configuration managed in the XML, and we don't have to pollute our business logic with any remoting-specific details.

    The code for the custom TargetSource is here:

    http://kay.za.net/code/JaxRpcPortTargetSource.java

    Note: any network failures would still propagate in the form of a RemoteAccessException - you could weave in an additional aspect if you wanted to potentially retry such calls transparently to the business component.

  • #2
    Thanks. Can you please raise an enhancement on JIRA; the code might get included in the main distribution.

    Comment


    • #3
      Done: http://opensource2.atlassian.com/pro...rowse/SPR-1688

      Comment

      Working...
      X