axis + spring 集成(2)

一.SpringAxisConstans

package com.skysuite.axis.spring;

import org.apache.axis.deployment.wsdd.WSDDConstants;

import javax.xml.namespace.QName;

public class SpringAxisConstans {

    
    public static final String PROVIDER_SPRINGRPC = "SPRINGRPC";
    public static final String PROVIDER_SPRINGMSG = "SPRINGMSG";
    
    public static final QName QNAME_JAVARPC_SPRINGPROVIDER = new QName(WSDDConstants.URI_WSDD_JAVA, PROVIDER_SPRINGRPC);
    public static final QName QNAME_JAVAMSG_SPRINGPROVIDER = new QName(WSDDConstants.URI_WSDD_JAVA, PROVIDER_SPRINGMSG);
    
    
}

2.AxisServlet

package com.skysuite.axis.spring;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;

import org.apache.axis.transport.http.AxisServlet;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContextException;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.util.StringUtils;
import org.springframework.web.context.ConfigurableWebApplicationContext;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.context.support.XmlWebApplicationContext;


public class SpringAxisServlet extends AxisServlet {

    private static final Log LOG = LogFactory.getLog(SpringAxisServlet.class);

    /**
     * Suffix for WebApplicationContext namespaces. If a SpringAxisServlet is
     * given the name "axis" in a context, the namespace used by this instance will
     * resolve to "axis-servlet".
     */
    public static final String DEFAULT_NAMESPACE_SUFFIX = "-servlet";

    /**
     * Default context class for SpringAxisServlet.
     *
     * @see org.springframework.web.context.support.XmlWebApplicationContext
     */
    public static final Class DEFAULT_CONTEXT_CLASS = XmlWebApplicationContext.class;

    /** Name of the ServletContext attribute for the WebApplicationContext */
    public static final String SERVLET_CONTEXT_ATTRIBUTE = SpringAxisServlet.class.getName()
            + ".CONTEXT";

    /** Custom WebApplicationContext class */
    private Class contextClass = DEFAULT_CONTEXT_CLASS;

    /** Namespace for this servlet */
    private String namespace;

    /** Explicit context config location */
    private String contextConfigLocation;

    /** WebApplicationContext for the SpringAxisServlet */
    private WebApplicationContext webApplicationContext;

    /**
     * Initialise the WebApplicationContext of the SpringAxisServlet.
     *
     * @see org.apache.axis.transport.http.AxisServlet#init()
     */
    public void init() throws ServletException {
        super.init();

        long startTime = System.currentTimeMillis();
        if (LOG.isDebugEnabled()) {
            LOG.debug("Servlet '" + getServletName() + "' init");
        }

        setContextClassName(getServletConfig().getInitParameter("contextClassName"));
        setContextConfigLocation(getServletConfig().getInitParameter("contextConfigLocation"));
        setNamespace(getServletConfig().getInitParameter("namespace"));

        try {
            this.webApplicationContext = initWebApplicationContext();
        } catch (BeansException ex) {
            LOG.error("Context initialization failed", ex);
            throw ex;
        }

        if (LOG.isDebugEnabled()) {
            long elapsedTime = System.currentTimeMillis() - startTime;
            LOG.debug("Servlet '"
                    + this.getServletName()
                    + "' init completed in "
                    + elapsedTime
                    + " ms");
        }
    }

    /**
     * Close the WebApplicationContext of the SpringAxisServlet.
     *
     * @see org.apache.axis.transport.http.AxisServletBase#destroy()
     */
    public void destroy() {
        super.destroy();

        log("Closing WebApplicationContext of servlet '" + getServletName() + "'");
        if (this.webApplicationContext instanceof ConfigurableApplicationContext) {
            ((ConfigurableApplicationContext) this.webApplicationContext).close();
        }
    }

    /**
     * Set a custom context class by name. This class must be of type WebApplicationContext,
     * when using the default SpringAxisServlet implementation, the context class
     * must also implement ConfigurableWebApplicationContext.
     *
     * @see #createWebApplicationContext
     */
    public void setContextClassName(String contextClassName) throws IllegalArgumentException {
        if (contextClassName != null) {
            try {
                ClassLoader loader = Thread.currentThread().getContextClassLoader();
                this.contextClass = Class.forName(contextClassName, true, loader);
            } catch (ClassNotFoundException e) {
                throw new IllegalArgumentException(e.getMessage());
            }
        }
    }

    /**
     * Set a custom context class. This class must be of type WebApplicationContext,
     * when using the default SpringAxisServlet implementation, the context class
     * must also implement ConfigurableWebApplicationContext.
     *
     * @see #createWebApplicationContext
     */
    public void setContextClass(Class contextClass) {
        this.contextClass = contextClass;
    }

    /**
     * Return the custom context class.
     */
    public Class getContextClass() {
        return contextClass;
    }

    /**
     * Set a custom namespace for the SpringAxisServlet,
     * to be used for building a default context config location.
     */
    public void setNamespace(String namespace) {
        this.namespace = namespace;
    }

    /**
     * Return the namespace for the SpringAxisServlet, falling back to default scheme if
     * no custom namespace was set: e.g. "axis-servlet" for a servlet named "axis".
     */
    public String getNamespace() {
        if (namespace != null) {
            return namespace;
        }
        return getServletName() + DEFAULT_NAMESPACE_SUFFIX;
    }

    /**
     * Set the context config location explicitly, instead of relying on the default
     * location built from the namespace. This location string can consist of
     * multiple locations separated by any number of commas and spaces.
     */
    public void setContextConfigLocation(String contextConfigLocation) {
        this.contextConfigLocation = contextConfigLocation;
    }

    /**
     * Return the explicit context config location, if any.
     */
    public String getContextConfigLocation() {
        return contextConfigLocation;
    }

    /**
     * Initialize and publish the WebApplicationContext for the SpringAxisServlet.
     * Delegates to createWebApplicationContext for actual creation.
     * Can be overridden in subclasses.
     *
     * @throws org.springframework.beans.BeansException
     *      if the context couldn't be initialized
     *
     * @see #createWebApplicationContext
     */
    protected WebApplicationContext initWebApplicationContext() throws BeansException {
        log("Initializing WebApplicationContext for servlet '" + this.getServletName() + "'");

        ServletContext ctx = getServletContext();
        WebApplicationContext parent = WebApplicationContextUtils.getWebApplicationContext(ctx);

        //WebApplicationContext wac = createWebApplicationContext(parent);
       
        WebApplicationContext wac = parent;
        if (LOG.isDebugEnabled()) {
            LOG.debug("Using context class '"
                    + wac.getClass().getName()
                    + "' for servlet '"
                    + getServletName()
                    + "'");
        }

        // publish the context as a servlet context attribute
        ctx.setAttribute(SERVLET_CONTEXT_ATTRIBUTE, wac);
        if (LOG.isDebugEnabled()) {
            LOG.debug("Published WebApplicationContext of servlet '"
                    + getServletName()
                    + "' as ServletContext attribute with name ["
                    + SERVLET_CONTEXT_ATTRIBUTE
                    + "]");
        }
        return wac;
    }

    /**
     * Instantiate the WebApplicationContext for the SpringAxisServlet, either a default
     * XmlWebApplicationContext or a custom context class if set. This implementation
     * expects custom contexts to implement ConfigurableWebApplicationContext.
     * Can be overridden in subclasses.
     *
     * @throws org.springframework.beans.BeansException
     *      if the context couldn't be initialized
     *
     * @see #setContextClass
     *
     * @see org.springframework.web.context.support.XmlWebApplicationContext
     */
    protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent)
        throws BeansException {

        if (LOG.isDebugEnabled()) {
            LOG.debug("Servlet with name '"
                    + getServletName()
                    + "' will try to create custom WebApplicationContext context of class '"
                    + getContextClass().getName()
                    + "'"
                    + " using parent context ["
                    + parent
                    + "]");
        }
        if (!ConfigurableWebApplicationContext.class.isAssignableFrom(getContextClass())) {
            throw new ApplicationContextException(
                "Fatal initialization error in servlet with name '"
                        + getServletName()
                        + "': custom WebApplicationContext class ["
                        + getContextClass().getName()
                        + "] is not of type ConfigurableWebApplicationContext");
        }

        ConfigurableWebApplicationContext wac = createContextInstance();
        wac.setParent(parent);
        wac.setServletContext(getServletContext());
        wac.setNamespace(getNamespace());

        if (this.contextConfigLocation != null) {
            wac.setConfigLocations(StringUtils.tokenizeToStringArray(
                this.contextConfigLocation,
                ConfigurableWebApplicationContext.CONFIG_LOCATION_DELIMITERS,
                true,
                true));
        }
        wac.refresh();
        return wac;
    }

    private ConfigurableWebApplicationContext createContextInstance() {
        return (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(getContextClass());
    }

    /**
     * Return the SpringAxisServlet's WebApplicationContext.
     */
    public final WebApplicationContext getWebApplicationContext() {
        return webApplicationContext;
    }
}

三.SpringAxisSetup

package com.skysuite.axis.spring;

import org.apache.axis.deployment.wsdd.WSDDProvider;

public class SpringAxisSetup {

    public SpringAxisSetup() {
        init();
    }

    public void init() {
        WSDDProvider.registerProvider(
                SpringAxisConstans.QNAME_JAVARPC_SPRINGPROVIDER,
                new WSDDSpringRPCProvider());
        WSDDProvider.registerProvider(
                SpringAxisConstans.QNAME_JAVAMSG_SPRINGPROVIDER,
                new WSDDSpringMsgProvider());
    }
}

四.SpringBeanMsgProvider

package com.skysuite.axis.spring;

import org.apache.axis.AxisFault;
import org.apache.axis.MessageContext;
import org.apache.axis.handlers.soap.SOAPService;
import org.apache.axis.providers.java.MsgProvider;

/**
 * Axis provider for message-style services that uses Spring Framework
 * to retrieve service classes and resolve their dependencies.
 * Simply delegates to {@link com.workingmouse.webservice.axis.SpringBeanProvider}.
 * <p>
 * To use this class:<br>
 * 1. Configure {@link com.workingmouse.webservice.axis.SpringAxisServlet} as your axis servlet in web.xml.
 * <pre>
 * &lt;servlet&gt;
 *   &lt;servlet-name&gt;axis&lt;/servlet-name&gt;
 *   &lt;display-name&gt;Apache-Axis Servlet&lt;/display-name&gt;
 *   &lt;servlet-class&gt;com.workingmouse.webservice.axis.SpringAxisServlet&lt;/servlet-class&gt;
 * &lt;/servlet&gt;
 * </pre>
 * 2. Configure your server-config.wsdd service to use this class as the service handler.
 * <pre>
 * &lt;service name=&quot;formRequest.jws&quot; provider=&quot;Handler&quot; style=&quot;message&quot;&gt;
 *   &lt;parameter name=&quot;handlerClass&quot; value=&quot;com.workingmouse.webservice.axis.SpringBeanMsgProvider&quot;/&gt;
 *   &lt;parameter name=&quot;wsdlTargetNamespace&quot; value=&quot;http://www.ioof.com.au/schemas&quot;/&gt;
 *   &lt;parameter name=&quot;springBean&quot; value=&quot;formRequestWS&quot;/&gt;
 * &lt;/service&gt;
 * </pre>
 * 3. Configure a Spring-managed bean in axis-servlet.xml that will act as the web service end point.
 * <pre>
 * &lt;bean id=&quot;formRequestWS&quot; class=&quot;com.workingmouse.webservice.forms.FormRequestWebService&quot;&gt;
 *   &lt;property name=&quot;documentServices&quot;&gt;&lt;ref bean=&quot;documentServices&quot;/&gt;&lt;/property&gt;
 * &lt;/bean&gt;
 * </pre>
 *
 */
public class SpringBeanMsgProvider extends MsgProvider {

    private final SpringBeanProvider provider = new SpringBeanProvider();

    /**
     * @see org.apache.axis.providers.java.JavaProvider#makeNewServiceObject(org.apache.axis.MessageContext, java.lang.String)
     */
    protected Object makeNewServiceObject(MessageContext msgContext, String clsName)
        throws Exception {

        return provider.getBean(msgContext, clsName);
    }

    /**
     * @see org.apache.axis.providers.java.JavaProvider#getServiceClass(java.lang.String, org.apache.axis.handlers.soap.SOAPService, org.apache.axis.MessageContext)
     */
    protected Class getServiceClass(String clsName, SOAPService service, MessageContext msgContext)
        throws AxisFault {

        return provider.getBeanClass(clsName);
    }

    /**
     * @see org.apache.axis.providers.java.JavaProvider#getServiceClassNameOptionName()
     */
    protected String getServiceClassNameOptionName() {
        return SpringBeanProvider.BEAN_OPTION_NAME;
    }
}

五.SpringBeanProvider

package com.skysuite.axis.spring;

import javax.servlet.ServletContext;
import javax.xml.rpc.ServiceException;
import javax.xml.rpc.server.ServletEndpointContext;

import org.apache.axis.Constants;
import org.apache.axis.MessageContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

/**
 *
 */
public class SpringBeanProvider {

    private Log log = LogFactory.getLog(getClass());
   
    /**
     * The server-config.wsdd service parameter used to provide the name of the
     * Spring-managed bean to use as the web service end-point.
     */
    public static final String BEAN_OPTION_NAME = "springBean";
    public static final String BEAN_CLASS_OPTION_NAME = "springBeanClass";

    private WebApplicationContext webAppCtx;

    /**
     * Return a bean bound with the given beanName from the WebApplicationContext.
     */
    public Object getBean(MessageContext msgContext, String beanName) throws Exception {
        initWebAppContext(msgContext);
        if (webAppCtx != null) {
            return webAppCtx.getBean(beanName);
        }
        else {
            return null;
        }
    }

    /**
     * Return the class of a bean bound with the given beanName in the WebApplicationContext.
     */
    public Class getBeanClass(String className) {
        Class result = null;
        try {
            result = Class.forName(className);
        }
        catch (ClassNotFoundException e) {
            log.debug("class "+className+" not found");
        }
        return result;
    }

    private void initWebAppContext(MessageContext msgContext) throws ServiceException {
        log.info("initializing app context for spring-axis integration");
        if (webAppCtx == null) {
            if (msgContext != null) {
                Object context = msgContext.getProperty(Constants.MC_SERVLET_ENDPOINT_CONTEXT);
                if (context instanceof ServletEndpointContext) {
                    ServletEndpointContext servletEndpointContext = (ServletEndpointContext) context;
                    ServletContext servletCtx = servletEndpointContext.getServletContext();               
                    webAppCtx = WebApplicationContextUtils.getWebApplicationContext(servletCtx);
                    if (webAppCtx == null) {
                        log.info("failed to retrieve webapp context for spring-axis integration");
                        throw new ServiceException(
                            "Cannot find WebApplicationContext from org.springframework.web.context.ContextLoaderListener");                                  
                    }
                } else {
                    log.info("failed to retrieve webapp context for spring-axis integration because this is an incorrect servlet context!");
                    throw new ServiceException("Invalid context - expected ["
                            + ServletEndpointContext.class.getName()
                            + "], actual ["
                            + context
                            + "]");
                }
            }
            else {
                log.info("null msg context!");
            }
        }
    }
}

六.SpringBeanRPCProvider

package com.skysuite.axis.spring;

import org.apache.axis.AxisFault;
import org.apache.axis.Handler;
import org.apache.axis.MessageContext;
import org.apache.axis.handlers.soap.SOAPService;
import org.apache.axis.providers.java.RPCProvider;

/**
 * <p>
 * To use this class:<br>
 * 1. Configure web.xml to use the axis servlet
 * 2. Configure web.xml to use the spring @see org.springframework.web.context.ContextLoaderListener.
 * 3. Configure your server-config.wsdd service to use this class as the service handler.
 *
 * Here is an example:
 * <pre>
 * &lt;service name="hdWebService.jws" provider="Handler" style="rpc"&gt;
 *      &lt;parameter name="handlerClass" value="com.workingmouse.webservice.axis.SpringBeanRPCProvider"/&gt;
 *      &lt;parameter name="wsdlTargetNamespace" value="http://healthdec.com"/&gt;
 *      &lt;parameter name="springBean" value="hdWebService"/&gt;
 *      &lt;parameter name="springBeanClass" value="com.healthdec.hdSOAPServer.WebService"/&gt;
 *      &lt;parameter name="allowedMethods" value="findAllInstances"/&gt;
 *      &lt;beanMapping qname="myNS:Instance" xmlns:myNS="urn:BeanService" languageSpecificType="java:com.healthdec.domain.dm.Instance"/&gt;
 *      &lt;beanMapping qname="myNS:CRFType" xmlns:myNS="urn:BeanService" languageSpecificType="java:com.healthdec.domain.dm.CRFType"/&gt;
 *      &lt;beanMapping qname="myNS:CRFQuestionType" xmlns:myNS="urn:BeanService" languageSpecificType="java:com.healthdec.domain.dm.CRFQuestionType"/&gt;
 * &lt;/service&gt;
 * </pre>
 *
 * 4. Configure a Spring-managed bean in your applicationContext xml file that will act as the web service end point.
 * <pre>
 * &lt;bean id=&quot;productWS&quot; class=&quot;com.skysuite.webservice.ProductWebServices&quot;&gt;
 * &lt;/bean&gt;
 * </pre>
 *
 */
public class SpringBeanRPCProvider extends RPCProvider {

    private final SpringBeanProvider provider = new SpringBeanProvider();
    private String serviceClassName;
    private String springBeanName;
   
   
    /* (non-Javadoc)
     * @see org.apache.axis.providers.BasicProvider#initServiceDesc(org.apache.axis.handlers.soap.SOAPService, org.apache.axis.MessageContext)
     *
     * Get the name and class of the Spring bean that will implement the Webservice methods.
     *
     */
    public void initServiceDesc(SOAPService service, MessageContext arg1)
            throws AxisFault {
        setServiceClassName((String)service.getOption(SpringBeanProvider.BEAN_CLASS_OPTION_NAME));
        setSpringBeanName((String)service.getOption(SpringBeanProvider.BEAN_OPTION_NAME));
        super.initServiceDesc(service, arg1);
    }
    /**
     * @see org.apache.axis.providers.java.JavaProvider#makeNewServiceObject(org.apache.axis.MessageContext, java.lang.String)
     */
    protected Object makeNewServiceObject(MessageContext msgContext, String clsName)
        throws Exception {
        if (msgContext != null) {
            return provider.getBean(msgContext, getSpringBeanName());
        }
        else {
            return null;
        }
    }

    /**
     * @see org.apache.axis.providers.java.JavaProvider#getServiceClass(java.lang.String, org.apache.axis.handlers.soap.SOAPService, org.apache.axis.MessageContext)
     */
    protected Class getServiceClass(String clsName, SOAPService service, MessageContext msgContext) {
        return provider.getBeanClass(clsName);
    }

    /**
     * @see org.apache.axis.providers.java.JavaProvider#getServiceClassNameOptionName()
     */
    protected String getServiceClassNameOptionName() {
        return SpringBeanProvider.BEAN_OPTION_NAME;
    }
    public void setServiceClassName(String serviceClassName) {
        this.serviceClassName = serviceClassName;
    }
    /**
     * @see org.apache.axis.providers.java.JavaProvider#getServiceClassName(org.apache.axis.Handler)
     */
    protected String getServiceClassName(Handler arg0) {
        return getServiceClassName();
    }

    /**
     * @return Returns the serviceClassName.
     */
    public String getServiceClassName() {
        return serviceClassName;
    }
    /**
     * @param serviceClassName The serviceClassName to set.
     */
   
    /**
     * @return Returns the springBeanName.
     */
    public String getSpringBeanName() {
        return springBeanName;
    }
    /**
     * @param springBeanName The springBeanName to set.
     */
    public void setSpringBeanName(String springBeanName) {
        this.springBeanName = springBeanName;
    }
}

七.WSDDSpringMsgProvider

package com.skysuite.axis.spring;

import org.apache.axis.EngineConfiguration;
import org.apache.axis.Handler;
import org.apache.axis.deployment.wsdd.WSDDProvider;
import org.apache.axis.deployment.wsdd.WSDDService;

public class WSDDSpringMsgProvider extends WSDDProvider{

    @Override
    public Handler newProviderInstance(WSDDService arg0, EngineConfiguration arg1) throws Exception {
        return new SpringBeanMsgProvider();
    }

    @Override
    public String getName() {
        return SpringAxisConstans.PROVIDER_SPRINGMSG;
    }

}

八. WSDDSpringRPCProvider
package com.skysuite.axis.spring;

import org.apache.axis.EngineConfiguration;
import org.apache.axis.Handler;
import org.apache.axis.deployment.wsdd.WSDDProvider;
import org.apache.axis.deployment.wsdd.WSDDService;

public class WSDDSpringRPCProvider extends WSDDProvider{

    @Override
    public Handler newProviderInstance(WSDDService arg0, EngineConfiguration arg1) throws Exception {
       
        return new SpringBeanRPCProvider();
    }

    @Override
    public String getName() {
       
        return SpringAxisConstans.PROVIDER_SPRINGRPC;
    }

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章