Можно ли использовать jax-ws для генерации xml, но НЕ отправлять его

Итак, вот сценарий: у нас есть PeopleSoft, и мы хотим отправлять сообщения из отдела продаж туда и обратно. К сожалению, у PeopleSoft нет такого инструмента, как wsimport, который использует wsdl и генерирует для вас классы. Есть что-то, что потребляет wsdl, но все, что он делает, это генерирует объекты сообщений-заглушек. Разработчику все равно придется писать код для ручного создания строки сообщения xml.

Я, очевидно, не хочу делать все это. Итак, я знаю, что java можно вызывать из PeopleSoft. Я также знаю, что могу отправлять сообщения, просто используя сгенерированные классы, но я хотел бы использовать функции мониторинга сообщений, встроенные в PeopleSoft.

Итак, возможное решение, о котором я думаю, будет:

  1. вызвать метод веб-сервиса в java (без отправки сообщения)
  2. Возьмите xml
  3. отправить xml через механизмы PeopleSoft
  4. получить ответ xml
  5. передать ответ xml обратно в класс ответа java
  6. Используйте классы Java для получения значений в XML

Я сумасшедший или это возможно?

p.s. я новичок в java разработчике

Вот мой класс обработчика для захвата xml, но нужен какой-то способ предотвратить отправку сообщения.

public class LoggingHandler implements SOAPHandler<SOAPMessageContext> {
 // change this to redirect output if desired
private static PrintStream out = System.out;
private String xmlOut = null;

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

public boolean handleMessage(SOAPMessageContext smc) {
    logToSystemOut(smc);
    return true;
}

public boolean handleFault(SOAPMessageContext smc) {
    logToSystemOut(smc);
    return true;
}

// nothing to clean up
public void close(MessageContext messageContext) {
}

public String getXmlOut() {
    return xmlOut;
}

/*
 * Check the MESSAGE_OUTBOUND_PROPERTY in the context
 * to see if this is an outgoing or incoming message.
 * Write a brief message to the print stream and
 * output the message. The writeTo() method can throw
 * SOAPException or IOException
 */
private void logToSystemOut(SOAPMessageContext smc) {
    Boolean outboundProperty = (Boolean)
        smc.get (MessageContext.MESSAGE_OUTBOUND_PROPERTY);


    SOAPMessage message = smc.getMessage();
    try {
        ByteArrayOutputStream baOut = new ByteArrayOutputStream();
        message.writeTo(baOut);
        xmlOut = new String(baOut.toByteArray());


    } catch (Exception e) {
        out.println("Exception in handler: " + e);
    }
}

}

person willard    schedule 02.02.2012    source источник


Ответы (3)


Существует систематический способ сделать это в веб-службах Java, JAX-WS. Просто примените шаблон перехватчика с помощью обработчика SOAP. Класс обработчика перехватит сообщение в методе handleMessage(SOAPMessageContext mc), делайте все, что хотите, с XML-телом SOAP-конверта. и остановить дальнейшую обработку SOAPMessage.

Затем вы можете обрабатывать XML по своему усмотрению (например, отправляя через механизм PeopleSoft). И когда от peoplesoft возвращается ответ, обойти цепочку исходящих обработчиков... (Мне действительно нужно посмотреть, как обойти цепочку). Я просто обкатываю идею, надо сделать POC. Я никогда этого не делал, иначе я бы поделился кодом. Но это абсолютно выполнимо.

person Asif Shahzad    schedule 07.02.2012
comment
Если вы пишете новую конечную точку веб-службы, отдайте предпочтение механизму на основе провайдера, а не механизму SEI JAX-WS, поскольку SEI предназначен для более высокой абстракции, и вы хотите работать с сгенерированным XML. - person Asif Shahzad; 07.02.2012
comment
Я реализовал класс обработчика, просмотрев примеры, но не уверен, как остановить дальнейшую обработку мыльного сообщения. Есть намеки на это? Вот мой класс обработчика: `public boolean handleMessage(SOAPMessageContext smc) { logToSystemOut(smc); вернуть истину; } private void logToSystemOut(SOAPMessageContext smc) { Сообщение SOAPMessage = smc.getMessage(); try { ByteArrayOutputStream baOut = new ByteArrayOutputStream(); сообщение.writeTo(baOut); xmlOut = новая строка (baOut.toByteArray()); } }` - person willard; 08.02.2012
comment
1. Я думаю, вы звоните в сервис от PeopleSoft, который выставляется SalesForce. Таким образом, вы должны определить обработчик на стороне клиента, потому что вы хотите перехватывать сообщение SOAP, которое генерирует среда выполнения на стороне клиента (чтобы вы могли пройти через механизм PeopleSoft). То, как вы определили обработчик, используется для определения обработчиков на стороне сервера. Обработчики на стороне клиента определяются по-разному. см. bit.ly/zGerml, чтобы получить представление. - person Asif Shahzad; 09.02.2012
comment
2. В определенном вами обработчике вы не проверяете, обрабатываете ли вы исходящие сообщения или входящие. Вы хотите изначально получить XML исходящего сообщения (на стороне PeopleSoft), поэтому просто добавьте if((Boolean) lmc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY)) {... }. - person Asif Shahzad; 09.02.2012
comment
3. Дальнейшая обработка обработчиков может быть прекращена возвратом false из handleMessage(..). Но главная проблема в том, что вы не только заинтересованы в прекращении дальнейшей обработки. Вы хотите приостановить дальнейшую обработку, чтобы получить ответ другим способом, а затем возобновить обработку с какого-то входящего сообщения. Понятия не имею, как это можно сделать :( Это очень сложно + интересно. - person Asif Shahzad; 09.02.2012
comment
Я в порядке с остановкой обработки. Мне просто нужен способ вернуть необработанный xml обратно в сгенерированный объект ответа, чтобы я мог читать оттуда свои значения. Спасибо за все ваши ответы! - person willard; 09.02.2012

Одним из решений может быть замена SocketFatory JAX-WS. Примерно это будет выглядеть так:

javax.net.SocketFactory socketFactory = new MySocketFactory();
Service service = Service.create(new URL(wsdl), new QName(namespace, servicename));
Dispatch<SOAPMessage> dispatch = service.createDispatch(methodToBeCalled, SOAPMessage.class, Service.Mode.MESSAGE);
dispatch.getRequestContext().put(com.sun.xml.ws.developer.JAXWSProperties.SSL_SOCKET_FACTORY, socketFactory);
// or ((BindingProvider) Service.getPort(SEIInterface.class)).getRequestContext().put(...);

А в MySocketFactory вы можете создавать сокеты, которые передают сообщение в другой канал.

person dma_k    schedule 03.02.2012

Когда вы говорите, что вам нужен только XML, вы говорите о сообщении SOAP или только о типах запроса/ответа? Я не уверен, что вы говорите о втором случае, но если вам нужен только XML, почему бы не использовать JAXB напрямую?

Если это так, вы можете извлечь схемы из WSDL, сгенерировать свои типы (скажем, у вас есть RequestA и ResponseA для операции «A» в WSDL) и использовать маршаллер/демаршаллер JAXB для сериализации/анализа XML. Затем отправьте его по протоколу, который вы хотите.

person Denian    schedule 08.02.2012
comment
Непосредственное использование JAXB потребует больших усилий, так как нам нужно не только XML-представление сообщений, но и полное сообщение SOAP, чтобы его могла понять конечная точка службы. И, во-вторых, когда среда выполнения JAX-WS также делает это, то не следует ли нам исследовать/повторно использовать ее вместо того, чтобы изобретать велосипед. - person Asif Shahzad; 09.02.2012