SpringBoot uses Axis to integrate Web Services

Keywords: Java Apache FileProvider xml

1. Prospect Review

In the previous chapter, I introduced SpringBoot's use of CXF to integrate Web Services. SpringBook Integrates Web Services with CXF What you want to know can be reviewed.

In this chapter, we will study how to integrate Axis, which is more complex than CXF integration.

2. SpringBook Integrated Web Service

2.1 Adding Dependencies

compile('org.springframework.boot:spring-boot-starter-web-services',
            'org.apache.axis:axis:1.4',
            'axis:axis-jaxrpc:1.4',
            'commons-discovery:commons-discovery:0.2',
            'wsdl4j:wsdl4j:1.6.3'
    )

My project is built using gradle, and Maven is the same. Just import the corresponding jar into the pom.

2.2 Add Servlet


import org.apache.axis.transport.http.AxisServlet;
import org.springframework.stereotype.Component;

/**
 * @author yueli
 * @date 2019-08-05 19:14
 */
@Component
@javax.servlet.annotation.WebServlet(
        urlPatterns =  "/axis/services/*",
        loadOnStartup = 1,
        name = "AxisServlet"
)
public class WebServlet extends AxisServlet {


}

Note: Field @ServletComponentScan annotation is required on the startup class to scan to our own defined Servlet.

2.3 Rewrite Axis Configuration Factory Information

Because we're going to use jar for publishing, we have to rewrite the configuration factory or we won't be able to access it. This direct copy can be used in the past.

/*
 * Copyright 2002-2004 The Apache Software Foundation.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.axis.configuration;

import org.apache.axis.AxisProperties;
import org.apache.axis.ConfigurationException;
import org.apache.axis.EngineConfiguration;
import org.apache.axis.EngineConfigurationFactory;
import org.apache.axis.components.logger.LogFactory;
import org.apache.axis.server.AxisServer;
import org.apache.axis.utils.ClassUtils;
import org.apache.axis.utils.Messages;
import org.apache.commons.logging.Log;

import javax.servlet.ServletConfig;
import java.io.InputStream;

/**
 * This is a default implementation of ServletEngineConfigurationFactory.
 * It is user-overrideable by a system property without affecting
 * the caller. If you decide to override it, use delegation if
 * you want to inherit the behaviour of this class as using
 * class extension will result in tight loops. That is, your
 * class should implement EngineConfigurationFactory and keep
 * an instance of this class in a member field and delegate
 * methods to that instance when the default behaviour is
 * required.
 *
 * @author Richard A. Sitze
 * @author Davanum Srinivas (dims@apache.org)
 */
public class EngineConfigurationFactoryServlet
        extends EngineConfigurationFactoryDefault {
    protected static Log log =
            LogFactory.getLog(EngineConfigurationFactoryServlet.class.getName());

    private ServletConfig cfg;

    /**
     * Creates and returns a new EngineConfigurationFactory.
     * If a factory cannot be created, return 'null'.
     * <p>
     * The factory may return non-NULL only if:
     * - it knows what to do with the param (param instanceof ServletContext)
     * - it can find it's configuration information
     *
     * @see EngineConfigurationFactoryFinder
     */
    public static EngineConfigurationFactory newFactory(Object param) {
        /**
         * Default, let this one go through if we find a ServletContext.
         *
         * The REAL reason we are not trying to make any
         * decision here is because it's impossible
         * (without refactoring FileProvider) to determine
         * if a *.wsdd file is present or not until the configuration
         * is bound to an engine.
         *
         * FileProvider/EngineConfiguration pretend to be independent,
         * but they are tightly bound to an engine instance...
         */
        return (param instanceof ServletConfig)
                ? new EngineConfigurationFactoryServlet((ServletConfig) param)
                : null;
    }

    /**
     * Create the default engine configuration and detect whether the user
     * has overridden this with their own.
     */
    protected EngineConfigurationFactoryServlet(ServletConfig conf) {
        super();
        this.cfg = conf;
    }

    /**
     * Get a default server engine configuration.
     *
     * @return a server EngineConfiguration
     */
    public EngineConfiguration getServerEngineConfig() {
        return getServerEngineConfig(cfg);
    }

    /**
     * Get a default server engine configuration in a servlet environment.
     *
     * @param cfg a ServletContext
     * @return a server EngineConfiguration
     */
    private static EngineConfiguration getServerEngineConfig(ServletConfig cfg) {

        // Respect the system property setting for a different config file
        String configFile = cfg.getInitParameter(OPTION_SERVER_CONFIG_FILE);
        if (configFile == null)
            configFile =
                    AxisProperties.getProperty(OPTION_SERVER_CONFIG_FILE);
        if (configFile == null) {
            configFile = SERVER_CONFIG_FILE;
        }

        /**
         * Flow can be confusing.  Here is the logic:
         * 1) Make all attempts to open resource IF it exists
         *    - If it exists as a file, open as file (r/w)
         *    - If not a file, it may still be accessable as a stream (r)
         *    (env will handle security checks).
         * 2) If it doesn't exist, allow it to be opened/created
         *
         * Now, the way this is done below is:
         * a) If the file does NOT exist, attempt to open as a stream (r)
         * b) Open named file (opens existing file, creates if not avail).
         */

        /*
         * Use the WEB-INF directory
         * (so the config files can't get snooped by a browser)
         */
        String appWebInfPath = "/WEB-INF";
        //Because the deployment mode has changed to jar deployment, you can't use this to get the path
//        ServletContext ctx = cfg.getServletContext();
//        String realWebInfPath = ctx.getRealPath(appWebInfPath);

        FileProvider config = null;
        String realWebInfPath = EngineConfigurationFactoryServlet.class.getResource(appWebInfPath).getPath();

        /**
         * If path/file doesn't exist, it may still be accessible
         * as a resource-stream (i.e. it may be packaged in a JAR
         * or WAR file).
         */
        InputStream iss = ClassUtils.getResourceAsStream(EngineConfigurationFactoryServlet.class, appWebInfPath+"/" + SERVER_CONFIG_FILE);
        if (iss != null) {
            // FileProvider assumes responsibility for 'is':
            // do NOT call is.close().
            config = new FileProvider(iss);
        }

        if (config == null) {
            log.error(Messages.getMessage("servletEngineWebInfError03", ""));
        }

        /**
         * Couldn't get data  OR  file does exist.
         * If we have a path, then attempt to either open
         * the existing file, or create an (empty) file.
         */
        if (config == null && realWebInfPath != null) {
            try {
                config = new FileProvider(realWebInfPath, configFile);
            } catch (ConfigurationException e) {
                log.error(Messages.getMessage("servletEngineWebInfError00"), e);
            }
        }

        /**
         * Fall back to config file packaged with AxisEngine
         */
        if (config == null) {
            log.warn(Messages.getMessage("servletEngineWebInfWarn00"));
            try {
                InputStream is =
                        ClassUtils.getResourceAsStream(AxisServer.class,
                                SERVER_CONFIG_FILE);
                config = new FileProvider(is);

            } catch (Exception e) {
                log.error(Messages.getMessage("servletEngineWebInfError02"), e);
            }
        }

        return config;
    }
}

2.4 Create resource files

Create the server-config.wdd file under WEB-INF

<?xml version="1.0" encoding="UTF-8"?>
<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
    <globalConfiguration>
        <parameter name="sendMultiRefs" value="true"/>
        <parameter name="disablePrettyXML" value="true"/>
        <parameter name="adminPassword" value="admin"/>
        <parameter name="attachments.Directory" value=""/>
        <parameter name="dotNetSoapEncFix" value="true"/>
        <parameter name="enableNamespacePrefixOptimization" value="false"/>
        <parameter name="sendXMLDeclaration" value="true"/>
        <parameter name="sendXsiTypes" value="true"/>
        <parameter name="attachments.implementation" value="org.apache.axis.attachments.AttachmentsImpl"/>
        <requestFlow>
            <handler type="java:org.apache.axis.handlers.JWSHandler">
                <parameter name="scope" value="session"/>
            </handler>
            <handler type="java:org.apache.axis.handlers.JWSHandler">
                <parameter name="scope" value="request"/>
                <parameter name="extension" value=".jwr"/>
            </handler>
        </requestFlow>
    </globalConfiguration>
    <handler name="URLMapper" type="java:org.apache.axis.handlers.http.URLMapper"/>
    <handler name="LocalResponder" type="java:org.apache.axis.transport.local.LocalResponder"/>
    <handler name="Authenticate" type="java:org.apache.axis.handlers.SimpleAuthenticationHandler"/>

    <service name="bdcgzcxfw_wx" provider="java:RPC" style="rpc" use="encoded">
        <parameter name="wsdlTargetNamespace" value="iptv"/>
        <parameter name="wsdlServiceElement" value="CSPRequestService"/>
        <parameter name="schemaUnqualified" value="iptv"/>
        <parameter name="wsdlServicePort" value="bdcgzcxfw_wx"/>
        <parameter name="className" value="com.tusdao.webservice.service.impl.WebServiceImpl"/>
        <parameter name="allowedMethods" value="*"/>
    </service>

    <service name="bdcgzcxfw" provider="java:RPC" style="rpc" use="encoded">
        <parameter name="wsdlTargetNamespace" value="iptv"/>
        <parameter name="wsdlServiceElement" value="CSPRequestService"/>
        <parameter name="schemaUnqualified" value="iptv"/>
        <parameter name="wsdlServicePort" value="bdcgzcxfw"/>
        <parameter name="className" value="com.tusdao.webservice.service.impl.BdcgzcxfwServiceImpl"/>
        <parameter name="allowedMethods" value="*"/>
    </service>

    <service name="scjdgl_jk" provider="java:RPC" style="rpc" use="encoded">
        <parameter name="wsdlTargetNamespace" value="iptv"/>
        <parameter name="wsdlServiceElement" value="CSPRequestService"/>
        <parameter name="schemaUnqualified" value="iptv"/>
        <parameter name="wsdlServicePort" value="scjdgl_jk"/>
        <parameter name="className" value="com.tusdao.webservice.service.impl.ScjdglInfoServiceImpl"/>
        <parameter name="allowedMethods" value="*"/>
    </service>

    <service name="zwww_jk" provider="java:RPC" style="rpc" use="encoded">
        <parameter name="wsdlTargetNamespace" value="iptv"/>
        <parameter name="wsdlServiceElement" value="CSPRequestService"/>
        <parameter name="schemaUnqualified" value="iptv"/>
        <parameter name="wsdlServicePort" value="zwww_jk"/>
        <parameter name="className" value="com.tusdao.webservice.service.impl.ZwwwJkServiceImpl"/>
        <parameter name="allowedMethods" value="*"/>
    </service>

    <service name="bdcappcxjk" provider="java:RPC" style="rpc" use="encoded">
        <parameter name="wsdlTargetNamespace" value="iptv"/>
        <parameter name="wsdlServiceElement" value="CSPRequestService"/>
        <parameter name="schemaUnqualified" value="iptv"/>
        <parameter name="wsdlServicePort" value="bdcappcxjk"/>
        <parameter name="className" value="com.tusdao.webservice.service.impl.AppServiceImpl"/>
        <parameter name="allowedMethods" value="*"/>
    </service>

    <service name="gzcxfw_gat" provider="java:RPC" style="rpc" use="encoded">
        <parameter name="wsdlTargetNamespace" value="iptv"/>
        <parameter name="wsdlServiceElement" value="CSPRequestService"/>
        <parameter name="schemaUnqualified" value="iptv"/>
        <parameter name="wsdlServicePort" value="gzcxfw_gat"/>
        <parameter name="className" value="com.tusdao.webservice.service.impl.BdcgzcxfwGatServiceImpl"/>
        <parameter name="allowedMethods" value="*"/>
    </service>

    <service name="szfgjjglj_jk" provider="java:RPC" style="rpc" use="encoded">
        <parameter name="wsdlTargetNamespace" value="iptv"/>
        <parameter name="wsdlServiceElement" value="CSPRequestService"/>
        <parameter name="schemaUnqualified" value="iptv"/>
        <parameter name="wsdlServicePort" value="szfgjjglj_jk"/>
        <parameter name="className" value="com.tusdao.webservice.service.impl.SzfgjjgljJkServiceImpl"/>
        <parameter name="allowedMethods" value="*"/>
    </service>

    <transport name="http">
        <requestFlow>
            <handler type="URLMapper"/>
            <handler type="java:org.apache.axis.handlers.http.HTTPAuthHandler"/>
        </requestFlow>
        <parameter name="qs:list" value="org.apache.axis.transport.http.QSListHandler"/>
        <parameter name="qs:wsdl" value="org.apache.axis.transport.http.QSWSDLHandler"/>
        <parameter name="qs.list" value="org.apache.axis.transport.http.QSListHandler"/>
        <parameter name="qs.method" value="org.apache.axis.transport.http.QSMethodHandler"/>
        <parameter name="qs:method" value="org.apache.axis.transport.http.QSMethodHandler"/>
        <parameter name="qs.wsdl" value="org.apache.axis.transport.http.QSWSDLHandler"/>
    </transport>
    <transport name="local">
        <responseFlow>
            <handler type="LocalResponder"/>
        </responseFlow>
    </transport>
</deployment>

All that remains is to develop the corresponding interface. I don't write much about it here. It's the same as our usual development and implementation of service interface.

If you feel that the above writing is messy and you can't understand it, you can see the source code: https://github.com/yuelicn/sp...

Posted by Gillesie on Tue, 01 Oct 2019 10:46:24 -0700