0

我在 WSO2 ESB 中创建了一个代理服务,该服务从没有参数的 web 服务获取请求,并基于 xml 文件进行响应。这是我的 WSDL(名为 itemcat.wsdl):

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions xmlns:scc="http://www.myplace.com/scc/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="ItemCategories"
    targetNamespace="http://www.myplace.com/scc/">
    <wsdl:types>
        <xsd:schema targetNamespace="http://www.myplace.com/scc/">
            <xsd:element name="ItemCategoriesRequest">
                <xsd:annotation>
                    <xsd:documentation>No parameter for request</xsd:documentation>
                </xsd:annotation>
                <xsd:complexType />
            </xsd:element>
            <xsd:element name="ItemCategoriesResponse">
                <xsd:complexType>
                    <xsd:sequence>
                        <xsd:element name="ItemCategories" type="scc:ItemCategoriesType" minOccurs="1" maxOccurs="1" />
                    </xsd:sequence>
                </xsd:complexType>
            </xsd:element>
            <xsd:complexType name="ItemCategoriesType">
                <xsd:sequence>
                    <xsd:element name="ItemCategory" type="scc:ItemCategoryType" minOccurs="0" maxOccurs="unbounded" />
                </xsd:sequence>
            </xsd:complexType>
            <xsd:complexType name="ItemCategoryType">
                <xsd:attribute name="value" use="required" type="scc:ValueType" />
                <xsd:attribute name="description" use="optional" type="scc:DescriptionType" />
            </xsd:complexType>
            <xsd:simpleType name="ValueType">
                <xsd:annotation>
                    <xsd:documentation>Unique category name</xsd:documentation>
                </xsd:annotation>
                <xsd:restriction base="xsd:string">
                    <xsd:maxLength value="30" />
                </xsd:restriction>
            </xsd:simpleType>
            <xsd:simpleType name="DescriptionType">
                <xsd:annotation>
                    <xsd:documentation>Category description</xsd:documentation>
                </xsd:annotation>
                <xsd:restriction base="xsd:string">
                    <xsd:maxLength value="255" />
                </xsd:restriction>
            </xsd:simpleType>
        </xsd:schema>
    </wsdl:types>
    <wsdl:message name="ItemCategoriesRequestMsg">
        <wsdl:part element="scc:ItemCategoriesRequest" name="parameters" />
    </wsdl:message>
    <wsdl:message name="ItemCategoriesResponseMsg">
        <wsdl:part element="scc:ItemCategoriesResponse" name="parameters" />
    </wsdl:message>
    <wsdl:portType name="ItemCategoriesPortType">
        <wsdl:operation name="getItemCategories">
            <wsdl:input message="scc:ItemCategoriesRequestMsg" name="ItemCategoriesRequest" />
            <wsdl:output message="scc:ItemCategoriesResponseMsg" name="ItemCategoriesResponse"/>
        </wsdl:operation>
    </wsdl:portType>
    <wsdl:binding name="ItemCategoriesSoap11Binding" type="scc:ItemCategoriesPortType">
        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
        <wsdl:operation name="getItemCategories">
            <soap:operation soapAction="itemcategories" />
            <wsdl:input>
                <soap:body use="literal" />
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal" />
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:service name="ItemCategoriesService">
        <wsdl:port binding="scc:ItemCategoriesSoap11Binding" name="ItemCategoriesEndPoint">
            <soap:address location="http://www.myplace.com/scc/itemcategories" />
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>

我的代理:

<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse" name="ItemCategoriesService" transports="http https" startOnLoad="true" trace="disable">
    <target>
        <inSequence>
            <sequence key="ItemCategoriesSequence"/>
        </inSequence>
        <outSequence/>
        <faultSequence/>
    </target>
    <publishWSDL key="gov:/scc/itemcat.wsdl"/>
    <parameter name="useOriginalwsdl">true</parameter>
    <parameter name="modifyUserWSDLPortAddress">true</parameter>
</proxy>

和顺序:

<sequence xmlns="http://ws.apache.org/ns/synapse" name="ItemCategoriesSequence">
    <header action="remove" name="To"/>
    <property action="set" name="RESPONSE" scope="default" type="STRING" value="true"/>
    <property action="remove" name="NO_ENTITY_BODY" scope="axis2"/>
    <property action="set" name="FileLocation" scope="default"
        type="STRING" value="/home/user/Desktop/itemcat.txt"/>
    <class name="com.myplace.esb.mediator.ItemCategoriesTextFile"/>
    <send/>
</sequence>

最后是用于解析文本文件的调解器(我使用 JABX 库 - 我没有在此处粘贴 ItemCategories.java 和 ItemCategory.java 文件,但它们很简单):

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;

import javax.validation.Validation;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;

import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMXMLBuilderFactory;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.LineIterator;
import org.apache.synapse.MessageContext;
import org.apache.synapse.mediators.AbstractMediator;

public class ItemCategoriesTextFile extends AbstractMediator {

    /**
     * Property name for file location.
     */
    private static final String FILE_LOCATION = "FileLocation";

    /**
     * File content parameters.
     */
    private static final int EXPECTED_COLUMNS = 2;
    private static final String COLUMN_SEPARATOR_REGEXP = "\\t";

    @Override
    public boolean mediate(MessageContext context) {
        final String property = (String) context.getProperty(FILE_LOCATION);
        if (property == null) {
            log.warn("Property [" + FILE_LOCATION + "] null");
            return false;
        }
        final ItemCategories categories = new ItemCategories();
        LineIterator it;
        try {
            it = FileUtils.lineIterator(new File(property));
        } catch (IOException e) {
            log.warn("Error processing file [" + property + "]", e);
            return false;
        }
        // iterate over each line
        try {
            while (it.hasNext()) {
                final String line = it.nextLine();
                final boolean parsed = parseLine(categories, line);
                if (!parsed) {
                    // something went wrong
                    return false;
                }
            }
        } finally {
            LineIterator.closeQuietly(it);
        }
        try {
            response(context, categories, ItemCategories.class);
        } catch (Exception e) {
            log.warn("Error processing xml", e);
            return false;
        }
        return true;
    }

    private boolean parseLine(final ItemCategories itemcats, final String line) {
        final String[] split = line.split(COLUMN_SEPARATOR_REGEXP,
                EXPECTED_COLUMNS);
        if (split.length != EXPECTED_COLUMNS) {
            log.warn("Expected [" + EXPECTED_COLUMNS
                    + "] or less columns for each line inside the file");
            return false;
        }
        final ItemCategory itemcat = new ItemCategory(split[0], split[1]);
        if (!Validation.buildDefaultValidatorFactory().getValidator()
                .validate(itemcat).isEmpty()) {
            log.warn("Constraints not satisfied for line [" + line + "]");
            return false;
        }
        itemcats.addItemCategory(itemcat);
        return true;
    }

    /**
     * 
     * @param context
     *            response message context.
     * @param data
     *            data that will go to xml.
     * @param clazz
     *            class on top of xml.
     * @throws Exception
     *             any problem parsing xml.
     */
    private void response(MessageContext context, final Object data,
            final Class<?> clazz) throws Exception {
        final JAXBContext jc = JAXBContext.newInstance(clazz);
        final Marshaller marshaller = jc.createMarshaller();
        final StringWriter writer = new StringWriter();
        // removes the <xml> tag
        marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
        marshaller.marshal(data, writer);
        final OMElement root = OMXMLBuilderFactory.createOMBuilder(
                new ByteArrayInputStream(writer.toString().getBytes()))
                .getDocumentElement();
        context.getEnvelope().getBody().addChild(root);
    }

这是文本文件(itemcat.txt):

Raw Raw
Component   General
Intermediate    Intermediate
Finished    Finished

使用 WSO2 ESB 控制台上的“尝试此服务”,我得到了好的结果:

<ItemCategories>
   <ItemCategory value="Intermediate" description="Intermediate"/>
   <ItemCategory value="Component" description="General"/>
   <ItemCategory value="Finished" description="Finished"/>
   <ItemCategory value="Raw" description="Raw"/>
</ItemCategories>

然后下一步是创建一个 Web 服务客户端。我正在使用 CXF。我使用了wsdl2java 命令并为此创建了所有类。这是主要课程:

public class Main {

    public static void main(String[] args) throws MalformedURLException {
        URL url = new URL("http://localhost:8280/services/ItemCategoriesService?wsdl");
        ItemCategoriesService service = new ItemCategoriesService(url);
        ItemCategoriesPortType port = service.getItemCategoriesEndPoint();
        ItemCategoriesResponse resp = port.getItemCategories(new ItemCategoriesRequest());
        ItemCategories itens = resp.getItemCategories();
        List<ItemCategory> list = itens.getItemCategory();
        for(ItemCategory t : list){
            System.out.println(t);
        }
    }

}

但我得到了一个 NullPointerException:

Exception in thread "main" java.lang.NullPointerException
    at Main.main(Main.java:20)

第 20 行是

   List<ItemCategory> list = itens.getItemCategory();

当我调试(使用 eclipse)中介代码时,我看到它里面的一切都很好。它返回正常。

谁能帮我找出为什么 web 服务客户端从服务器接收 null ?

4

0 回答 0