Проблемы веб-служб Apache CXF

У меня есть многомодульный проект с использованием Maven. В одном из модулей у меня есть несколько веб-сервисов, разработанных с использованием Apache CXF Framework 2.5.4. На данный момент у меня есть две "проблемы" или вопросы.

Прежде всего, если я вызову метод одного из веб-сервисов, который должен вернуть List, если список пуст, он возвращает & quot; null & quot; вместо пустого списка. Я пытался выяснить, в чем может быть проблема, если это ошибка в CXF-версии, которую я использую, или если мне нужно использовать какую-то аннотацию для изменения определения метода или ответа, но я не смог найти ничего , Я видел некоторых людей с такой же проблемой, но без решения.

Еще одна вещь, которую я хотел спросить: я занимаюсь разработкой веб-приложения с использованием шаблона MVC. Мне интересно, каким образом мне следует вызывать веб-сервис из контроллера, а не использовать ClasspathXmlCpplicationContext, а затем context.getBean ().

Например, определение компонента для одной из веб-служб на стороне клиента:

<jaxws:client id="deviceWSClient"
        serviceClass="..IDeviceWebService"
        address="http://localhost:8080/../DeviceWS" /> 

Я уже пробовал использовать аннотации @Autowired или @WebServiceRef. С этим он работает, но не выполняет HTTP-запрос к веб-сервису, я думаю, он получает зависимость от локального репозитория. Я думаю, что мне нужен способ внедрения этого компонента в контроллер.

 Mavericks12 июл. 2012 г., 22:25
Любая специальная конфигурация для конечной точки или клиентских компонентов? Любая аннотация в коде веб-службы? Я сейчас пытаюсь 2.6.1. Спасибо
 Biju Kunjummen11 июл. 2012 г., 22:06
Я проверил с версиями 2.4.0 и 2.6.1 Apache CXF, пустой список обрабатывается правильно в обеих этих версиях.

Ответы на вопрос(2)

@WebServiceRef вероятно работает, если вы следуетеэта ссылка на весеннем форуме, Там вы используете другой способ для конфигурации Jaxws. Смотрите последний пост в списке.

Другие способы определения клиента обсуждаются наэтот ТАК вопрос, Например, есть решение, в котором вы, наконец, используете@Autowired аннотация после того, как вы дали дополнительную конфигурацию. Смотрите последний ответ на вопрос.

Другая проблема, о которой вы упоминали, была оэтот cxf список связанный вопрос где также указано решение для обхода проблемы. Так что это ошибка. В версии 2.2.7 это исправлено, но снова в версии 2.2.9 проблема возникла снова. Странно, что до вашей версии 2.5.4 он снова в состоянии ошибки. Вы можете попробовать обойти все еще, если это решит проблему для вас.

 Mavericks12 июл. 2012 г., 22:26
Спасибо за Ваш ответ. Я попробую последние версии CXF и Spring и проверим зависимости maven, чтобы проверить, не пропустил ли я их.
Решение Вопроса

For your first question: Если список пуст, он корректно обрабатывается версией CXF 2.6.1 - служба возвращает пустую. Просто чтобы продемонстрировать, у меня есть пример сервиса, в котором типы определяются следующим образом:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "MemberSearchResponse", namespace="http://bk.org/memberservice/" )
public class MemberSearchResponse {

    @XmlElementWrapper(name="memberDetails")
    private List<MemberDetail> memberDetails;

Если я верну пустой член memberDetails выше, xml, который идет по проводам, будет таким:

    <ns2:searchMemberResponse xmlns:ns2="http://bk.org/memberservice/">
        <ns2:MemberSearchResponse>
           <memberDetails/>
        </ns2:MemberSearchResponse>
    </ns2:searchMemberResponse>

EDIT

Он корректно обрабатывается как часть типа оболочки, как описано выше, но ДОЛЖЕН возвращать значение null, если вместо возврата типа оболочки список возвращается напрямую.

Рассмотрим интерфейс Webservice, определенный следующим образом:

@WebMethod(operationName = "searchMember")
    List<MemberDetail> searchMember(@WebParam(name = "MemberSearchRequest") MemberSearchRequest memberSearchRequest);

Если возвращаемый список является пустым списком, он также сериализуется как нулевой в CXF 2.6.1.

The workaround is to use a wrapper type

EDIT END

For your second question:

Вы создаете клиентский компонент следующим образом:

<jaxws:client id="deviceWSClient"
        serviceClass="..IDeviceWebService"
        address="http://localhost:8080/../DeviceWS" /> 

После того, как вы создали Spring bean таким образом, вы можете обращаться с ним как с обычным Spring bean и внедрять его так же, как вы это делаете с любым обычным Spring bean, например, либо внедрить его следующим образом:

 <bean id="consumerBean" class="...">
    <property name="deviceWS" ref="deviceWSClient">
 </bean>

или использовать@Autowired

@Autowired IDWebService deviceWSClient

Или пользователь@Resource

@Resource IDWebService deviceWSClient

Это обычные способы введения в боб.

В этом месте на github у меня есть пример приложения, с которым вы можете поиграть: https://github.com/bijukunjummen/memberservice-codefirst.git

Просто запустите сервер, используяmvn tomcat:run и запустить тестorg.bk.memberservice.TestCxfIntegrationTest который сделает запрос к сервису CXF.

 Mavericks14 июл. 2012 г., 11:58
Еще раз спасибо, ваш ответ был очень очень полезным. Наконец я решил обе проблемы.
 Mavericks13 июл. 2012 г., 18:49
Большое спасибо. Я решил мой второй вопрос, используя @Autowired. Проблема заключалась в том, что я использовал deviceWebService вместо deviceWSClient для именования переменной, поэтому он внедрял компонент веб-службы вместо клиента. Что касается первого вопроса, что вы имеете в виду? Я должен определить класс для ответа?
 13 июл. 2012 г., 20:28
О, я не осознавал, что вы возвращаете список напрямую, я по какой-то причине предположил, что вы завернули его в другой тип ответа. Вы правы, он возвращает ноль для таких случаев. Обходной путь - это то, что я использовал, чтобы использовать оболочку ответа, как я делал выше. Это работает.

Ваш ответ на вопрос