Spring boot RestTemplate публикует сообщение об ошибке 400 - PullRequest
0 голосов
/ 19 декабря 2018

Я написал простой веб-сервис на Java 8 для Eclipse Photon, использующий RestTemplate для публикации (используя postForObject) объекта (называемого патентListWrapper), который упаковывает список объектов (называемый PatentDetails).Я отправляю сообщение из клиента Java (называемого MainWsClient), затем устанавливаю значение вatentDetails на стороне сервера и считываю объектatentListWrapper обратно на клиенте.Это работает нормально, когда на стороне сервера (программа SpringWebServiceHello) использует старую технологию Spring MVC 4 с единственным файлом jar (Spring-web.5.07.RELEASE.jar), следующим за этим - serverSideExample , то есть web.xml и остальные-servlet.xml файлы, контролирующие точку доступа.Затем я написал другую серверную программу (PndGuidRequestWs), используя SpringBoot 2.03 с jar-файлами Spring 5.07 и Maven с идентичным методом @RequestMapping, но без файла web.xml и точки доступа, определенной в файле application.properties:

server.port=8082
server.servlet.path=/
#spring.mvc.servlet.path=/
#server.servlet.contextPath=/

Когда я вызываю эту новую серверную программу с помощью этого клиента - ARC , она также работает нормально, но когда я вызываю ее, используя тот же Java-клиент и точно такой же запрос (очевидно, принимаю для другого URL).Я получаю ошибку 400:

2018-12-18 16:56:53,861 [main] INFO  - Running MainWsClient with name = DS fileType = post3
2018-12-18 16:56:54,101 [main] DEBUG - Created POST request for "http://localhost:8082/guidRequest/xmlList"
2018-12-18 16:56:54,145 [main] DEBUG - Setting request Accept header to [application/xml, text/xml, application/json, application/*+xml, application/*+json]
2018-12-18 16:56:54,152 [main] DEBUG - Writing [com.springservice.client.PatentListWrapper@4ba2ca36] using [org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter@3444d69d]
2018-12-18 16:56:54,384 [main] DEBUG - POST request for "http://localhost:8082/guidRequest/xmlList" resulted in 400 (null); invoking error handler
2018-12-18 16:56:54,387 [main] ERROR - DS1B org.springframework.web.client.HttpClientErrorException: 400 null

Не работающая, PndGuidRequestWs, на стороне сервера имеет:

@RestController
public class PndController {

@RequestMapping(value = "/guidRequest/xmlList", method = RequestMethod.POST, produces = { "application/xml" } )
public PatentListWrapper guidSearchList(@RequestBody  PatentListWrapper patentListWrapper) {

    for (PatentDetails pd : patentListWrapper.getPatentList())
    {
        pd.setGuid("guidSetOnServer3");
    }

    return patentListWrapper;
  }

}

Рабочая (SpringWebServiceHello) сторона сервера идентична, за исключением:

value = "/service/greeting/xml/post2"

Клиент Java имеет:

public void runCode(String name , String fileType)
{

 String url;

 if (fileType.equalsIgnoreCase("post2")) {
        url = "http://localhost:8080/SpringWebServiceHello/service/greeting/xml/post2";
        // This method is identicle to postToPndGuidRequestWs() but this method works fine.
        postToSpringWebServiceHello(url);
    }else if (fileType.equalsIgnoreCase("post3")) {
        url = "http://localhost:8082/guidRequest/xmlList";      
        // This method gives 404 error          
        postToPndGuidRequestWs(url);
    }   
}

private void postToPndGuidRequestWs(String url) 
{

    PatentListWrapper patentListWrapper = new PatentListWrapper();
    PatentDetails pd = new PatentDetails("CN","108552082","A","00000000",12345,"guidIn");

    List<PatentDetails> patentList = new ArrayList<PatentDetails>();
    patentList.add(pd);
    patentListWrapper.setPatentList(patentList);

    RestTemplate restTemplate = new RestTemplate();

    /* HttpHeaders headers = new HttpHeaders();
    headers.add("header_name", "header_value");
    headers.setContentType(MediaType.APPLICATION_XML);
    HttpEntity<PatentListWrapper> request = new HttpEntity<PatentListWrapper>(patentListWrapper, headers); */

    /*List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
    Jaxb2RootElementHttpMessageConverter jaxbMessageConverter = new Jaxb2RootElementHttpMessageConverter();
    List<MediaType> mediaTypes = new ArrayList<MediaType>();
    mediaTypes.add(MediaType.APPLICATION_XML);
    jaxbMessageConverter.setSupportedMediaTypes(mediaTypes);
    messageConverters.add(jaxbMessageConverter);
    restTemplate.setMessageConverters(messageConverters);*/

    /* headers = new HttpHeaders();
    headers.setAccept(Collections.singletonList(MediaType.APPLICATION_XML));
    HttpEntity<String> entity = new HttpEntity<>("parameters", headers);*/


    try {
        patentListWrapper = restTemplate.postForObject(
                url,
                patentListWrapper,
                PatentListWrapper.class);


        logger.debug("DS1A employee obj returned. guid = " +  patentListWrapper.getPatentList().get(0).getGuid());
    }catch(Exception e) {
        logger.error("DS1B " + e);      
    }   
}

}

т.е. fileType = "post2" вызывает SpringWebServiceHello, fileType = "post3" вызывает PndGuidRequestWs.Как видите, я пробовал несколько закомментированных решений, но ничего не работает.Поскольку единственное реальное различие между двумя программами на стороне сервера заключается в том, что ни одна из работающих программ использует загрузку Spring, а рабочая - нет, проблема заключается в настройке SpringBoot, т.е. в структуре каталогов, application.properties или pom.xml.Мой pom.xml содержит:

<?xml version="1.0" encoding="UTF-8"?>

http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0

<groupId>com.clarivate</groupId>
<artifactId>pndguidrequestws</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>

<name>pndGuidRequestWs</name>
<description>Guid request webService</description>

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.3.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
    <start-class>com.clarivate.pndguidrequestws.PndGuidRequestWsApplication</start-class>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
    </dependency>

    <dependency>
        <groupId>com.oracle</groupId>
        <artifactId>ojdbc6</artifactId>
        <version>11.2.0.1.0</version> 
      <!--    <scope>provided</scope> --> <!-- DS insert for unix -->
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.apache.tomcat</groupId>
                <artifactId>tomcat-jdbc</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <!-- Implementing XML Representation for Spring Boot Services -->
    <dependency>
      <groupId>com.fasterxml.jackson.dataformat</groupId>
      <artifactId>jackson-dataformat-xml</artifactId>
    </dependency>

    <!-- httpcomponents jars are Required by PndGuidGenerator -->
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpcore</artifactId>
    </dependency>

    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
    </dependency>
</dependencies>


<build>
    <finalName>PndGuidRequestWs</finalName>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId> 
            <configuration>
                  <executable>true</executable>
            </configuration> 
        </plugin>
    </plugins>      
</build>
</project>

Класс PatentListWrapper:

package com.clarivate.pndguidrequestws.model;

import java.util.List;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class PatentListWrapper {

private List<PatentDetails> patentList;

public PatentListWrapper() {}

public List<PatentDetails> getPatentList() {
    return patentList;
}

public void setPatentList(List<PatentDetails> patentList) {
    this.patentList = patentList;
}   

}

Любые предложения приветствуются.

РЕДАКТИРОВАТЬ: Чтобы упростить объект, я создал PatentListWrapper2 только с одним строковым членом:

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class PatentListWrapper2 {

private String name;

public  PatentListWrapper2() {}

public  PatentListWrapper2(String name) {
    this.name = name;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

}

Я снова могу успешно отправить этот XML с помощью клиента ARC:

<patentListWrapper2>
   <name>DSDS</name>
</patentListWrapper2>

с contentType = "application / xml", но когда я пытаюсь отправить патентуListWrapper2 из Java, я получаю непоправимую ошибку:

 2018-12-20 09:17:13,931 [main] INFO  - Running MainWsClient with name = DS fileType = post4
2018-12-20 09:17:14,166 [main] DEBUG - Created POST request for "http://localhost:8082/guidRequest/xmlList2"
2018-12-20 09:17:14,200 [main] DEBUG - Setting request Accept header to [application/xml, text/xml, application/json, application/*+xml, application/*+json]
2018-12-20 09:17:14,206 [main] DEBUG - Writing [com.springservice.client.PatentListWrapper2@517cd4b] using [org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter@6cc7b4de]
2018-12-20 09:17:14,246 [main] DEBUG - POST request for "http://localhost:8082/guidRequest/xmlList2" resulted in 200 (null)
2018-12-20 09:17:14,248 [main] DEBUG - Reading [com.springservice.client.PatentListWrapper2] as "application/xml;charset=UTF-8" using [org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter@6cc7b4de]
2018-12-20 09:17:14,255 [main] ERROR - DS2B org.springframework.web.client.RestClientException: Error while extracting response for type [class com.springservice.client.PatentListWrapper2] and content type [application/xml;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: Could not unmarshal to [class com.springservice.client.PatentListWrapper2]: unexpected element (uri:"", local:"PatentListWrapper2"). Expected elements are <{}patentListWrapper2>; nested exception is javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"PatentListWrapper2"). Expected elements are <{}patentListWrapper2>

EDIT2 Я запустил pndGuidRequestWs в Eclipse Tomcat вместо - Запускать как -> Spring Boot App,Журнал сервера ниже:

2018-12-20 11:15:45.655  WARN 236 --- [nio-8080-exec-6] .w.s.m.s.DefaultHandlerExceptionResolver : Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot construct instance of `com.clarivate.pndguidrequestws.model.PatentDetails` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('CN'); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.clarivate.pndguidrequestws.model.PatentDetails` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('CN') at [Source: (PushbackInputStream); line: 1, column: 98] (through reference chain: com.clarivate.pndguidrequestws.model.PatentListWrapper["patentList"]->java.util.ArrayList[0])         

Ответы [ 2 ]

0 голосов
/ 20 декабря 2018

PatentListWrapper - это сложный объект, а не кусок xml, поэтому ответ состоит в том, чтобы удалить все ссылки на xml, например

  1. Remove @XmlRootElement (name = "PatentListWrapper") из PatentListWrapper.
  2. Добавьте jackson - *. Jar (s) в путь к классам для преобразования сообщений
  3. Измените на стороне сервера @RequestMapping с:

    @RequestMapping(value = "/xmlList", method = RequestMethod.POST , consumes = { "application/xml" }, produces = { "application/xml" }) 
    

до

@RequestMapping(value = "/xmlList", method = RequestMethod.POST )

Это означает, что клиент ARC теперь возвращает JSON (так как это тип возврата по умолчанию), даже когда я отправляю xml, но это не важно, поскольку это всего лишь инструмент тестирования.

Таким образом, при публикации объектов с RestTemplate в Spring 2 не требуется никаких настроек contentType или дополнительных конвертеров сообщений на стороне клиента, просто:

RestTemplate restTemplate = new RestTemplate();
MyObject myObjectReturn = restTemplate.postForObject(url,myObject,MyObject.class);

и на стороне сервера:

@RestController
@RequestMapping(value = "/endPoint", method = RequestMethod.POST)
public MyObject anyMethodName(@RequestBody  MyObject myObject) {
     //Do stuff to myObject
     return myObject;
}
0 голосов
/ 19 декабря 2018

Можете ли вы проверить с:

try {
        HttpHeaders headers = new HttpHeaders();
        //headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
        //headers.setContentType((MediaType.APPLICATION_JSON));
        // I comment the code abouve because you did not specify a consumes whitch  defines the media types that the methods of 
        //a resource class or MessageBodyReader can accept. If not specified, a container will assume that any media type is acceptable.
        HttpEntity<PatentListWrapper> request = new HttpEntity<>(patentListWrapper, headers);
        PatentListWrapper patentListWrapperResult =  = restTemplate.exchange(url, HttpMethod.POST, request,PatentListWrapper.class);


        logger.debug("DS1A employee obj returned. guid = " +  patentListWrapper.getPatentList().get(0).getGuid());
    }catch(Exception e) {
        logger.error("DS1B " + e);      
    } 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...