Получение и обработка нескольких предметов в JAX-WS

1

Я разрабатываю WebService JAX-WS для записи состояния журналов приложений клиентов.

Я посылаю по каждому запросу сообщение id, timestamp и status. WS только записывает это в базу данных.

Служба работает отлично, и я использую ее с Delphi, делая XML-запросы "вручную".

Поэтому меня не интересует клиентская сторона обслуживания. Клиент - это приложение Delphi, и я не могу его изменить...

Я могу использовать этот JAX-WS только один запрос за раз. Каждое обновление состояния состоит из полного вызова WS.

Проблема заключается в следующем: как я могу отправить много информации о состоянии в одном запросе, и, в частности, как мне нужно аннотировать JAX-WS для распознавания нескольких элементов в XML и дать мне в кубе функции реализации доступ ко всем элементам, таким как массив.

Я отправляю XML в WS в Delphi с помощью этого кода:

function JAXWS_getResponse( vXMLRequest_Envelope : WideString; vURL : String ) : WideString;
var sRequest : TStringStream;
    sResponse : TStringStream;
    JAXWS_Request : THTTPReqResp;
begin

  sRequest      := TStringStream.Create( vXMLRequest_Envelope );
  sResponse     := TStringStream.Create( EmptyStr );
  JAXWS_Request := THTTPReqResp.Create( nil );
  try

    JAXWS_Request.URL := vURL;
    JAXWS_Request.UseUTF8InHeader := True;

    JAXWS_Request.Execute( sRequest, sResponse );

    Result := sResponse.DataString;

  finally
    JAXWS_Request.Free;
    sRequest.Free;
    sResponse.Free;
  end;

end;

Содержимое параметра vXMLRequest_Envelope похоже (сделайте "вручную"):

<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <soapenv:Body>
    <ns2:updateStatus
        xmlns:ns2="http://webVersao.microdata.com.br/">
      <id_customer>123</id_customer>
      <status_date>2014-08-26 15:30:05</status_date>
      <status_message>WORKING</status_message>
    </ns2:updateStatus>
  </soapenv:Body>
</soapenv:Envelope>

Итак, это код веб-сервиса:

WebVersao_Interface.java

package br.com.microdata.webVersao;

import java.util.Date;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;

@WebService
@SOAPBinding(style = Style.RPC)
public interface WebVersao_Interface {

  @WebMethod
  String updateStatus(
      @WebParam(name="id_customer", partName="id_customer")
      String id_customer,
      @WebParam(name="status_date", partName="status_date")
      String status_date, // yyyy-mm-dd hh:nn:ss
      @WebParam(name="status_message", partName="status_message")
      String status_message
  );

}

WebVersao_Implementation.java

package br.com.microdata.webVersao;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Date;

import javax.jws.WebService;

@WebService(endpointInterface = "br.com.microdata.webVersao.WebVersao_Interface")
public class WebVersao_Implementation implements WebVersao_Interface {

  @Override
  public String updateStatus(String id_customer, String status_date, String status_message) {

    Connection conn = WebVersao_Connection.getConnection();

    try {

      Statement stmt = conn.createStatement();

      String query = 
          "insert into status_log ( id_customer, status_date, status_message ) " +
          String.format( "values ( %d, timestamp '%s', '%s' )",
                  id_customer, status_date, status_message );

      stmt.execute(query);

      return "DONE";

    } catch (SQLException e) {

      return "ERROR: " + e.getMessage();

    }

  }
}

Итак, наконец, мой вопрос:

Как я могу сделать свой XML следующим:

    <status>
      <id_customer>123</id_customer>
      <status_date>2014-08-26 12:30:05</status_date>
      <status_message>WAITING</status_message>
    </status>
    <status>
      <id_customer>789</id_customer>
      <status_date>2014-08-26 13:43:52</status_date>
      <status_message>SLEEPING</status_message>
    </status>
    <status>
      <id_customer>123</id_customer>
      <status_date>2014-08-26 15:30:05</status_date>
      <status_message>WORKING</status_message>
    </status>
    <status>
      <id_customer>456</id_customer>
      <status_date>2014-08-26 18:10:08</status_date>
      <status_message>SLEEPING</status_message>
    </status>

и правильно принимать в Java, как:

public String updateManyStatus( List<StatusInfo> manyStatus) { ... }

или

public String updateManyStatus( StatusInfo[] manyStatus) { ... }

или любой другой подобный метод...

public class StatusInfo {

  private Long id_customer;
  private String status_date;
  private String status_message;
  public Long getId_customer() {
    return id_customer;
  }
  public void setId_customer(Long id_customer) {
    this.id_customer = id_customer;
  }
  public String getStatus_date() {
    return status_date;
  }
  public void setStatus_date(String status_date) {
    this.status_date = status_date;
  }
  public String getStatus_message() {
    return status_message;
  }
  public void setStatus_message(String status_message) {
    this.status_message = status_message;
  }

}

Спасибо заранее всем сообществу StackOverflow. Вы все рок!

  • 0
    Вам нужен новый метод веб-службы с подписью, где параметром in является List <Status>
  • 0
    хорошо, но как я могу это сделать?
Теги:
soap
web-services
jax-ws

2 ответа

0
Лучший ответ

Вот как я решил свой собственный вопрос.

Далеко от элегантного решения, но мне он нужен, и это решает мою проблему.

Пожалуйста, кто-нибудь, кто знает, как это сделать лучше, прокомментируйте.

Мне не нравится этот подход, но я не знаю, как это сделать лучше!

Ну, есть мое решение:

Я просто замаскирую свой XML множеством элементов в одном параметре <xml_content>, а затем в Java, разоблачаю, разбираю как обычный XML и заполняю массив.

Мой запрос XML:

<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <soapenv:Body>
    <ns2:updateStatusMulti
        xmlns:ns2="http://webVersao.microdata.com.br/">
      <xml_content>

        {?xml version="1.0" encoding="utf-8"?}
        {many_status}
          {status}
            {id_customer}123{/id_customer}
            {status_date}2014-08-26 12:30:05{/status_date}
            {status_message}WAITING{/status_message}
          {/status}
          {status}
            {id_customer}789{/id_customer}
            {status_date}2014-08-26 13:43:52{/status_date}
            {status_message}SLEEPING{/status_message}
          {/status}
          {status}
            {id_customer}123{/id_customer}
            {status_date}2014-08-26 15:30:05{/status_date}
            {status_message}WORKING{/status_message}
          {/status}
          {status}
            {id_customer}456{/id_customer}
            {status_date}2014-08-26 18:10:08{/status_date}
            {status_message}SLEEPING{/status_message}
          {/status}
        {/many_status}

      </xml_content>
    </ns2:updateStatusMulti>
  </soapenv:Body>
</soapenv:Envelope>

то я добавил эту функцию в webservice inteface:

@WebMethod
String updateStatusMulti(
    @WebParam(name="xml_content", partName="xml_content")
    String xml_content);

и в реализации я заполняю массив и вызываю функцию updateManyStatus на моем пути, как я хочу!

@Override 
public String updateStatusMulti( String xml_content ) {

  try{

    //"unmask" then xml
    xml_content = xml_content.replace('{', '<');
    xml_content = xml_content.replace('}', '>');

    DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
    Document doc = dBuilder.parse(new InputSource(new ByteArrayInputStream(xml_content.getBytes("utf-8"))));

    //optional, but recommended
    //read this - http://stackoverflow.com/questions/13786607/normalization-in-dom-parsing-with-java-how-does-it-work
    doc.getDocumentElement().normalize();

    NodeList nList = doc.getElementsByTagName("status");

    int nCount = nList.getLength();

    StatusInfo[] manyStatus = new StatusInfo[nCount];

    for (int index = 0; index < nCount; index++) {

      Node nNode = nList.item(index);

      //("\nCurrent Element :" + nNode.getNodeName());

      if (nNode.getNodeType() == Node.ELEMENT_NODE) {

        Element eElement = (Element) nNode;

        String id_customer    = eElement.getElementsByTagName("id_customer").item(0).getTextContent();
        String status_date    = eElement.getElementsByTagName("status_date").item(0).getTextContent();
        String status_message = eElement.getElementsByTagName("status_message").item(0).getTextContent();

        manyStatus[index].setId_customer( Long.valueOf(id_customer) );
        manyStatus[index].setStatus_date( status_date );
        manyStatus[index].setStatus_message( status_message );

      }
    }

    //return String.format( "DONE: ( %d )", nCount );


    //here is my wanted call
    return updateManyStatus( manyStatus );

  } catch (Exception e) {

    return "ERROR: " + e.getMessage(); //xml_content;

  }
}

В любом случае, спасибо всем!

Скалы StackOverflow!

0

Наверное, ты почти там.

Во-первых, вам нужно изменить стиль привязки SOAP на "WebVersao_Interface" от @SOAPBinding(style = Style.RPC) до @SOAPBinding(style = Style.DOCUMENT). Стиль RPC имеет минимальную поддержку для определенных пользователем типов данных или сложных типов.

Любая из этих подписей в веб-сервисе

public String updateManyStatus( ArrayList<StatusInfo> manyStatus) {... }

или

public String updateManyStatus( StatusInfo[] manyStatus) {... }

Порекомендовал бы использовать версию массива для проблем совместимости для использования веб-сервиса для других клиентов без java.

И в клиенте, почему вы кодируете xml-сообщение. Вместо этого вы можете создавать/заполнять все объекты StatuInfo; поместите их в массив или список и вызовите соответствующий метод webservice. Дай мне знать, если это работает.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню