Преобразовать SOAP в виртуальный сервис Restful? - PullRequest
1 голос
/ 20 июня 2011

Есть ли способ использовать мой веб-сервис SOAP (spring-ws, java) как сервис RESTful на основе XML?

Я не хочу переписывать весь мой веб-сервис SOAP в RESTful с нуля в java, но мне нужно получить к нему доступ через iphone, используя REST, который уже имеет простую встроенную поддержку.

XMLGateway, Proxys ..? или какой-то дополнительный код Java? мой SOAP-запрос и ответ - это просто файл XML, почему я не могу изменить его для использования службой REST?

Или, не меняя логику и парсинг xml в моем приложении, так легко добавить аннотации jax-rs и создать xml-запрос на отдых?

мой файл конфигурации весны выглядит так:

<bean id="webServicePluginDescriptor"
    class="com.mysite.ws.configuration.MyWebservicePluginDescriptor" />

<bean id="payloadMapping"
    class="org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping">
    <property name="defaultEndpoint" ref="inferenceEndPoint" />
    <property name="interceptors">
        <list>
            <ref local="validatingInterceptor" />
            <ref local="payLoadInterceptor" />
        </list>
    </property>
</bean>

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

<bean id="validatingInterceptor"
    class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor">
    <property name="schema"
        value="classpath:/wsdl/Request.xsd" />
    <property name="validateRequest" value="true" />
    <property name="validateResponse" value="false" />
</bean>

<bean id="PropertyResource" class="com.mysite.ws.im.PropertyResource">
    <property name="resource"
        value="/WEB-INF/client-specific/InferenceMachine.properties" />
</bean>

<bean id="inferenceEndPoint" class="com.mysite.ws.web.InferenceEndPoint">
    <property name="messageWebService" ref="messageWebService" />
</bean>
<bean id="messageWebService" class="com.mysite.ws.service.MessageWebService"
    scope="request">
    <aop:scoped-proxy />
    <property name="inferenceService" ref="inferenceService" />
</bean>

<bean id="Request" class="org.springframework.xml.xsd.SimpleXsdSchema">
    <property name="xsd" value="classpath:/wsdl/Request.xsd" />
</bean>

<bean id="Response" class="org.springframework.xml.xsd.SimpleXsdSchema">
    <property name="xsd" value="classpath:/wsdl/Response.xsd" />
</bean>

<bean id="Error" class="org.springframework.xml.xsd.SimpleXsdSchema">
    <property name="xsd" value="classpath:/wsdl/Error.xsd" />
</bean>

<bean id="mwsid"
    class="org.springframework.ws.wsdl.wsdl11.SimpleWsdl11Definition">
    <constructor-arg value="classpath:/wsdl/mtchwsdl.wsdl" />
</bean>

<bean id="inferenceService" class="com.mysite.ws.im.InferenceService"
    scope="request">
    <aop:scoped-proxy />
    <property name="webServiceConfiguration" ref="wsPlayerConfiguration" />

    <property name="properties">
        <bean class="com.mysite.ws.im.PropertyResource">
            <property name="resource"
                value="/WEB-INF/client-specific/InferenceMachine.properties" />
        </bean>
    </property>
</bean>

<!-- ~~~~~~~ Application beans ~~~~~~~ -->
<bean id="wsPlayerConfiguration"
    class="com.mysite.ws.configuration.WebServiceConfiguration"
    scope="request">
    <aop:scoped-proxy />
    <property name="playerConfiguration" ref="playerConfiguration"></property>
    <property name="configurationSetup" ref="configurationSetup"></property>
</bean>

и это мой класс конечной точки:

/**
 * The EndPoint of the Web Service Application. This class gets the raw
 * SOAP-body message from the Spring Payload Dispatcher and sends the message to
 * the @see MessageService class. After it has gotten the response XML message
 * it returns this back to the Spring Payload Dispatcher.
 */
public class InferenceEndPoint extends AbstractJDomPayloadEndpoint {

    private MessageWebService messageWebService;
    public InferenceEndPoint() {
    }

    @Override
    protected Element invokeInternal(Element inferenceRequest) throws Exception {
        Element ret = messageWebService.handleRequest(inferenceRequest);
        return ret;
    }

    /**
     * @param messageWebService
     */
    public void setMessageWebService(MessageWebService messageWebService) {
        this.messageWebService = messageWebService;
    }
}

есть идеи?

Ответы [ 3 ]

2 голосов
/ 20 июня 2011

Spring-WS просто добавляет некоторые аннотации к вашим bean-компонентам, и тогда у вас есть bean-компоненты Spring, выполняющие большую часть тяжелой работы. Предположительно у вас есть некоторые классы, аннотированные @Endpoint, @PayloadRoot и тому подобное. Вы должны быть в состоянии повторно использовать все это одним из трех способов.

Если ваши классы конечных точек Spring-WS имеют стиль шаблона адаптера (например, ваш класс Endpoint внедряется с помощью службы POJO, которая выполняет реальную работу), то вы можете создать аналогичный контроллер MVC Spring-типа в стиле адаптера (где REST существует в Spring 3.0).

Если у вас есть аннотации непосредственно в вашем классе бизнес-логики, то теоретически вы можете просто добавить несколько аннотаций (может выглядеть немного занятым).

Если у вас есть bean-компоненты Spring-WS, которые являются POX (а не SOAP), то вам, возможно, удастся избежать некоторых причудливых отображений URL, чтобы дать им более RESTful выглядящие URL

Чтобы перейти на Spring 3 для поддержки REST, добавьте соответствующий @RequestMapping и другие аннотации, чтобы представить их как службы REST для соответствия определенным URL-адресам. Пока вы добавляете, вы также можете удалить старые @PayloadRoots и @Endpoint, но это может не иметь большого значения. Конечно, если вы оставите старые аннотации Spring-WS рядом, вам все равно понадобятся jar-файлы Spring-WS на вашем пути к классам, но если вы не используете ни сервлет Spring-WS, ни какие-либо другие bean-компоненты в своем файле Spring - вы должно быть в порядке (в теории ...).

Самые большие ошибки будут:

  • Не забудьте удалить компоненты Spring-WS из вашего файла Spring
  • НЕ забудьте добавить bean-компоненты Spring MVC в файл Spring и, что важнее всего, другой сервлет Dispatcher
  • Безопасность REST в Spring будет обеспечиваться Spring Security, а не теми перехватчиками SOAP, которые есть в Spring-WS, так что это будет полный пересмотр. Хорошей новостью является то, что Spring Security на самом деле довольно легко работать с
2 голосов
/ 20 июня 2011

Глядя на ваш код, очень сложно сказать, каким будет лучший подход. REST и SOAP - это действительно разные способы представить, как может работать интерфейс веб-сервиса: SOAP - это вызовы методов, а REST - это ресурсы, представления и ссылки. Чтобы конвертировать, вы должны начать с базового абстрактного API.

Если ваш базовый API является одним из «Я даю вам документ, вы даете мне документ с ответом», и нет ничего другого, кроме этого, то это очень SOAP-ориентированная модель. Вы можете смоделировать это в REST, разместив документ и получив ответ, но это совсем не элегантно. Если вы вместо этого можете думать о своем интерфейсе в терминах «вот общий ресурс, со свойствами, которые я могу установить, и некоторыми операциями, которые я могу выполнять», то это гораздо проще отображает REST (общий ресурс представлен в виде документа, полного ссылок для отдельных ресурсов и операций свойств, а отдельные свойства могут быть GET и PUT - и, возможно, DELETEd - по мере необходимости). Какой стиль у вас есть ... ну, похоже, что у вас первый, но я только догадываюсь, потому что для его определения на самом деле потребуется посмотреть больше кода, чем вы показали.

1 голос
/ 20 июня 2011

Ничто не мешает вам отправить POST, заполненный XML, чтобы получить результаты, заполненные XML обратно.

Самое простое, что нужно сделать, это каким-то образом перехватить запросы SOAP, идущие туда-сюда, и просто превратить запрос в шаблон с пробелами, являющимися вашими параметрами, а затем использовать XPath в полученном XML для вывода ваших результатов.

Единственное, что вам может понадобиться - заголовок SOAPAction в вашем POST, но, скорее всего, нет.

Это действительно ничего страшного. Если у вас есть десятки методов, это больше боли. Кроме того, если вы используете какую-либо часть шифрования SOAP, то это больше проблем. Но если их всего несколько, то в конце концов это всего лишь XML, и большая часть этого XML является шаблонной, так что если смотреть с точки зрения, это довольно просто.

Addenda:

Если у вас есть внутренняя логика, которую вы хотите использовать с более дружественным HTTP-сервисом, то JAX-RS может сделать это довольно легко, но для этого потребуется кодирование на стороне сервера.

Если у вас есть существующая веб-служба SOAP, которую вы хотите использовать, то забудьте всю часть уравнения SOAP и просто относитесь к ней как к веб-службе HTTP, которая использует полезные нагрузки XML. Это все еще SOAP, но вы не используете никаких инструментов SOAP на стороне клиента. Вы просто собираете полезные нагрузки XML по клиентским запросам (из шаблонов было бы проще всего, ИМХО) и в результате потребляете полезные нагрузки XML и торгуете ими по HTTP.

В зависимости от того, сколько различных методов в существующем веб-сервисе вы намереваетесь вызывать, вы получите представление о масштабах выполняемой работы. Это простая работа (как только вы можете легко просматривать полезные данные), но она все еще работает. Если у вас есть только несколько методов, особенно если интерфейс стабилен и не меняется, гораздо проще просто работать с необработанным XML, чем изучать и бороться с какой-то новой незнакомой средой.

...