简体   繁体   English

Jaxb为终端指定Marshaller

[英]Jaxb specify Marshaller for Endpoint

I am using the Spring framework. 我正在使用Spring框架。

I have multiple mashallers and multiple endpoints. 我有多个混搭程序和多个端点。 The Jaxb context for my marshallers are defined with xml-binding files (using the eclipselink-oxm-xml jaxbContextProperties) since I have multiple marshalling tasks. 因为我有多个编组任务,所以编组器的Jaxb上下文是使用xml绑定文件定义的(使用eclipselink-oxm-xml jaxbContextProperties)。 Using annotations was not a good solution because the same object requires a different marshalling/unmarshalling procedure depending on endpoint. 使用注释不是一个好的解决方案,因为根据端点,同一对象需要不同的编组/解组过程。

My configuration at the moment for a single JaxbMarshaller and Endpoint looks like so: 目前,我对单个JaxbMarshaller和Endpoint的配置如下所示:

<sws:annotation-driven marshaller="marshallerA" unmarshaller="marshallerA"/>        

    <bean id="loggingInterceptor"
        class="org.springframework.ws.server.endpoint.interceptor.PayloadLoggingInterceptor"/>


    <bean id="messageReceiver"
        class="org.springframework.ws.soap.server.SoapMessageDispatcher">
        <property name="endpointAdapters">
            <list>
                <ref bean="defaultMethodEndpointAdapter" />
            </list>
        </property>
    </bean> 

    <bean id="defaultMethodEndpointAdapter" 
        class="org.springframework.ws.server.endpoint.adapter.DefaultMethodEndpointAdapter">
        <property name="methodReturnValueHandlers">
            <list>
                <ref bean="marshallingPayloadMethodProcessor"/>
            </list>
        </property>
        <property name="methodArgumentResolvers">
            <list>
                <ref bean="marshallingPayloadMethodProcessor"/>
            </list>
        </property>     
    </bean>  


    <bean id="marshallingPayloadMethodProcessor"
        class="org.springframework.ws.server.endpoint.adapter.method.MarshallingPayloadMethodProcessor">
        <constructor-arg ref="marshallerA" />
        <constructor-arg ref="marshallerA" />
    </bean> 


    <bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping">
        <property name="order" value="1" />
    </bean>

    <sws:dynamic-wsdl id="myEndpointA"
        portTypeName="WebService"
        locationUri="/ws/myEndpointServiceA/"
        targetNamespace="http://company.com/schema/webServices" >

        <sws:xsd location="classpath:/path/to/schema/mySchemaA.xsd"/>

    </sws:dynamic-wsdl>

    <bean id="marshallerA" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
        <property name="contextPath" value="x.y.z:x.y.w"/>
            <property name="jaxbContextProperties">
            <util:map>
                <entry key="eclipselink-oxm-xml">
                    <list>
                         <value>file:/bindingFileOne.xml</value>
                         <value>file:/bindingFileTwo.xml</value>
                         <value>file:/bindingFileThree.xml</value>    
                    </list>
                </entry>
            </util:map>
        </property>
    </bean>

Now say I have a second endpoint and a second marshaller, how can I force an Endpoint to use a specific marshaller? 现在说我有第二个端点和第二个编组器,如何强制一个端点使用特定的编组器?

Thanks for any help! 谢谢你的帮助! :) :)

I ended up extending the DefaultMethodEndpointAdapter, creating SpecificEndpointAdapter. 我最终扩展了DefaultMethodEndpointAdapter,创建了SpecificEndpointAdapter。 I only need to override one method, the implementation is as follows: 我只需要重写一种方法,实现如下:

public class SpecificEndpointAdapter extends DefaultMethodEndpointAdapter {
    private List<Object> acceptedEndpoints;

    public void setAcceptedEndpoints(List<Object> acceptedEndpoints) {
        this.acceptedEndpoints = acceptedEndpoints;
    }

    @Override
        protected boolean supportsInternal(MethodEndpoint methodEndpoint) {
        if(acceptedEndpoints.contains(methodEndpoint.getBean()))
            return super.supportsInternal(methodEndpoint);
        return false;
    }
}

In my context file, this allows me to restrict an endpoint adapter to a specific endpoint, thus having a specific marshaller: 在我的上下文文件中,这允许我将端点适配器限制为特定的端点,从而具有特定的编组器:

<bean id="serviceAEndpointAdapter" class="my.package.SpecificEndpointAdapter">
    <property name="acceptedEndpoints">
        <list>
            <ref bean="serviceAEndpoint"/>
        </list>
    </property>
    <property name="methodReturnValueHandlers">
        <list>
            <ref bean="serviceA.marshallingPayloadMethodProcessor"/>
        </list>
    </property>
    <property name="methodArgumentResolvers">
        <list>
            <ref bean="serviceA.marshallingPayloadMethodProcessor"/>
        </list>
    </property>     
</bean>    

<bean id="serviceBEndpointAdapter" class="my.package.SpecificEndpointAdapter">
    <property name="acceptedEndpoints">
        <list>
            <ref bean="serviceBEndpoint"/>
        </list>
    </property>      
    <property name="methodReturnValueHandlers">
        <list>
            <ref bean="serviceB.marshallingPayloadMethodProcessor"/>
        </list>
    </property>
    <property name="methodArgumentResolvers">
        <list>
            <ref bean="serviceB.marshallingPayloadMethodProcessor"/>
        </list>
    </property>     
</bean>    

In my MarhsallingPayloadProcessor I can now declare which marshaller to use. 现在,在我的MarhsallingPayloadProcessor中,可以声明要使用哪个编组器。 Note that I ended up using the bean id as the SpecificEndpointAdapter reference, so if you are using annotations, you will need to figure out the bean id of that endpoint. 请注意,我最终将bean id用作SpecificEndpointAdapter引用,因此,如果您使用的是注释,则需要弄清楚该端点的bean id。

I hope this helps anyone who was facing the same issue, let me know if the answer requires more clarification. 希望这对遇到相同问题的所有人有所帮助,如果答案需要更多说明,请告诉我。

Just clarifying some points of the accepted answer, you can make the reference do the Endpoint just receiving as parameter the endpoint, like a normal bean: 只需澄清已接受答案的某些点,就可以使引用做Endpoint,就像接收普通端点一样,将端点作为参数接收:

@Bean
public SpecificEndpointAdapter csvEndpointAdapter(MyEndpoint myEndpoint) {

    List<MethodArgumentResolver> argumentResolvers =
            new ArrayList<>();
    argumentResolvers.add(methodProcessor());

    List<MethodReturnValueHandler> returnValueHandlers =
            new ArrayList<>();
    returnValueHandlers.add(methodProcessor());

    SpecificEndpointAdapter specificEndpointAdapter = new SpecificEndpointAdapter();
    specificEndpointAdapter.setMethodArgumentResolvers(argumentResolvers);
    specificEndpointAdapter.setMethodReturnValueHandlers(returnValueHandlers);
    specificEndpointAdapter.setAcceptedEndpoints(Arrays.asList(myEndpoint));

    return specificEndpointAdapter;
}

private MarshallingPayloadMethodProcessor methodProcessor() {
    return new MarshallingPayloadMethodProcessor(marshaller());
}

private Jaxb2Marshaller marshaller() {
    Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
    marshaller.setContextPath("com.company.application");
    marshaller.setMtomEnabled(true);
    return marshaller;
}

The MyEndpoint : MyEndpoint

@Endpoint
public class MyEndpoint {
   //...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM