Java/JAX-WS: вызов веб-службы работает локально, на стеклянной рыбе происходит сбой. Проблема с аутентификацией (SP0105)

Что я хочу сделать, так это написать фрагмент кода (часть более крупного веб-приложения, развернутого на стеклянной рыбе), который подключается к другой системе через веб-сервис. Однако я пишу только клиент, поэтому я предполагаю, что не могу изменить WSDL или что-либо изменить на стороне сервера (включая аутентификацию, здесь, вероятно, проблема). Я новичок в веб-сервисах, поэтому, пожалуйста, пишите свои ответы как можно проще.

Мне удалось сгенерировать классы из WSDL, написать простое приложение командной строки, которое подключается к веб-сервису, добавляет заголовок безопасности (добавьте имя пользователя/пароль в виде открытого текста, подробнее ниже), вызывает какой-то метод и выводит результат. Все работает нормально в командной строке, но если я прикреплю этот код к «большому веб-приложению» (развернув на стеклянной рыбе), я получаю следующую ошибку:

SP0105: в файле wsdl должно присутствовать любое утверждение SymmetricBinding/AsymmetricBinding/TransportBinding.

Я не получаю его оттуда - если он работает из командной строки (вне Glassfish), зачем ему что-то еще при развертывании на Glassfish?

Я использовал подсказки с этой страницы: http://www.javadb.com/using-a-message-handler-to-alter-the-soap-header-in-a-web-service-client

Чтобы дать больше информации об этом, некоторые фрагменты кода:

Фрагмент кода для разрешения конечной точки и вызова службы (в файле EndpointResolver.java):

URL baseUrl = EndpointResolver.class.getResource(".");
url = new URL(baseUrl, "WSDL_file.xml");

QName qname = new QName(SomeConfig.NAMESPACE, SomeConfig.LOCAL_PART);

Service service = Service.create(url, qname);

service.setHandlerResolver(headerHandlerResolver);

endpoint = service.getPort(MyPortType.class);

endpoint.doSomething();
//printing results here ..

HeaderHandlerResolver (реализующий javax.xml.ws.handler.HandlerResolver) наиболее важный метод:

public List<Handler> getHandlerChain(PortInfo portInfo) {
    List<Handler> handlerChain = new ArrayList<Handler>();

    handlerChain.add(headerHandler); //injected to HeaderHandlerResolver

    return handlerChain;
}

Метод обработки HeaderHandler (авторизация здесь :))

public boolean handleMessage(SOAPMessageContext smc) {

    Boolean outboundProperty = (Boolean) smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);

    if ( outboundProperty.booleanValue() ) {

        SOAPMessage message = smc.getMessage();

        try {

            SOAPEnvelope envelope = smc.getMessage().getSOAPPart().getEnvelope();
            SOAPHeader header = envelope.addHeader();

            SOAPElement security = header.addChildElement("Security", "wsse",
                    "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");

            SOAPElement usernameToken = security.addChildElement("UsernameToken", "wsse");
            usernameToken.addAttribute(new QName("xmlns:wsu"), "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");

            SOAPElement username = usernameToken.addChildElement("Username", "wsse");

            username.addTextNode("myUsername");

            SOAPElement password = usernameToken.addChildElement("Password", "wsse");
            password.setAttribute("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText");

            password.addTextNode("myPassword");

        } catch (SOAPException e) {
            log.warn(e.getMessage());
            e.printStackTrace();
        }

    } else {
        try {

            //This handler does nothing with the response from the Web Service so
            //we just print out the SOAP message.
            logSOAPMessage(smc.getMessage());

        } catch (Exception ex) {
            log.warn(ex.getMessage());
            ex.printStackTrace();
        }
    }

    return outboundProperty;

}

@Override
public Set<QName> getHeaders() {
   return null;
}
(...)

Большое спасибо за любую помощь в этом.

изменить: Ниже приведена часть «политики» из файла wsdl (как указано ранее, я не могу это изменить):

<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="UsernameToken">
    <wsp:ExactlyOne>
        <wsp:All>
            <sp:SupportingTokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
                <wsp:Policy>
                    <sp:UsernameToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient"/>
                </wsp:Policy>
            </sp:SupportingTokens>
        </wsp:All>
    </wsp:ExactlyOne>
</wsp:Policy>

person Peter    schedule 12.09.2011    source источник


Ответы (1)


Отвечу на свой вопрос:

Для устранения проблемы, описанной выше, требовалось две вещи. Первым делом потребовалось обновить библиотеку метро на Glassfish (я обновил ее до версии 2.1.1, поэтому обновил библиотеки lib/webservices-rt.jar, lib/webservices-tools.jar, lib/endorsed/webservices-api .банка). Это решило ошибку SP0105, но создало новую (ClassCastException где-то в заголовках). Чтобы исправить второй, я удалил классы HeaderHandler/HeaderHandlerResolver и вместо:

service.setHandlerResolver(headerHandlerResolver);
endpoint = service.getPort(EFormsPortType.class);

называется:

endpoint = service.getPort(EFormsPortType.class);
Map<String, Object> requestContext = ((javax.xml.ws.BindingProvider) endpoint).getRequestContext();
requestContext.put(javax.xml.ws.BindingProvider.USERNAME_PROPERTY, config.getProperty("myUser");
requestContext.put(javax.xml.ws.BindingProvider.PASSWORD_PROPERTY, config.getProperty("myPassword");
person Peter    schedule 15.09.2011