matsukaz's blog

Agile, node.js, ruby, AWS, cocos2d-xなどなどいろいろやってます

Spring Web Services まとめ その4

アノテーションの利用(Chapter 5)

endpointの実装には、AbstractXXXEndpointクラスを継承する他に、@Endpointアノテーションを利用する方法も用意されている。
@Endpointを利用した場合の特徴は以下の通り。

    • 実装するクラスはPOJO
    • 1つのクラス内に複数のendpointに対するハンドリングが記述できる。

以下は、@Endpointを利用した実装例である。

package samples;

import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;

@Endpoint
public class AnnotationOrderEndpoint {
    private final OrderService orderService;

    public AnnotationOrderEndpoint(OrderService orderService) {
        this.orderService = orderService;
    }

    @PayloadRoot(localPart = "orderRequest", namespace = "http://samples")
    public Order getOrder(OrderRequest orderRequest) {
        return orderService.getOrder(orderRequest.getId());
    }

    @PayloadRoot(localPart = "order", namespace = "http://samples")
    public void order(Order order) {
        orderService.createOrder(order);
    }

}

複数のendpointに対するハンドリングを行うため、各メソッドでは@PayloadRootアノテーションを記述し、受け取ったメッセージと処理を行うメソッドを関連付けている。この例では、メッセージに対してはgetOrder(OrderRequest)、メッセージに対してはorder(Order)を関連付けている。
引数となるOrderRequestやOrderオブジェクトは、いずれかのMarshallerを利用することでXMLメッセージから変換されている。
以下は、SpringのコンフィギュレーションXMLにJAXB 2.0のMarshallerを指定した例である。

<beans>
    <bean id="orderEndpoint" class="samples.AnnotationOrderEndpoint">
        <constructor-arg ref="orderService"/>
    </bean>

    <bean id="orderService" class="samples.DefaultOrderService"/>

    <bean class="org.springframework.ws.server.endpoint.adapter.MarshallingMethodEndpointAdapter">
        <constructor-arg ref="marshaller"/>
    </bean>

    <bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
        <property name="classesToBeBound">
            <list>
                <value>samples.OrderRequest</value>
                <value>samples.Order</value>
            </list>
        </property>        
    </bean>

    <bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping"/>

</beans>

また、@XPathParamアノテーションXMLメッセージをXPath指定することで、Marshallerを利用せずにメソッドの引数にオブジェクトを利用することもできる。以下はその例である。

package samples;

import javax.xml.transform.Source;

import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
import org.springframework.ws.server.endpoint.annotation.XPathParam;

@Endpoint
public class AnnotationOrderEndpoint {
    private final OrderService orderService;

    public AnnotationOrderEndpoint(OrderService orderService) {
        this.orderService = orderService;
    }

    @PayloadRoot(localPart = "orderRequest", namespace = "http://samples")
    public Source getOrder(@XPathParam("/s:orderRequest/@id") double orderId) {
        Order order = orderService.getOrder((int) orderId);
        // create Source from order and return it
    }

}