# Spring Rest Api



## Albus (9. Jul 2017)

Hallo liebe Community,

ich versuche aktuell mit Spring Boot externe Rest-Schnittstellen zu konsumieren. Ich habe dies mit folgendem Tutorial auch sehr erfolgreich umgesetzt.

https://spring.io/guides/gs/consuming-rest/

Leider gelingt es mit jedoch nur bei Rest-Schnitstellen welche vom Content-Type *application/json utf8 *sind. Aktuell versuche ich vom ITIS den Rest Service zu konsumieren welcher dem Application-Type* text/json* bietet. 

https://itis.gov/ITISWebService/jsonservice/getFullRecordFromTSN?tsn=202384

Auch mein Versuch den Header umszustellen scheitert leider.

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity entity = new HttpEntity( headers);
ResponseEntity<String> result = restTemplate.exchange("https://itis.gov/ITISWebService/jsonservice/getFullRecordFromTSN?tsn=202384",HttpMethod.GET, entity, String.class);
log.info(result.getBody());

Als String lässt er sich jedoch erfolgreich Konsumieren.

String quote = restTemplate.getForObject(
        "https://itis.gov/ITISWebService/jsonservice/getFullHierarchyFromTSN?tsn=558090", String.class);
log.info(quote.toString());

Daher sehe ich aktuell zwei Möglichkeiten entweder gelint es den Headertypen text/json zu akzeptieren oder den konsumierten String als Json zu lesen.

Beide Möglichkeiten sind mir bis dato jedoch nicht gelungen. Hab Ihr mir einen Tipp?

Freundliche Grüße 
Albus


----------



## Flown (9. Jul 2017)

Ich verstehe jetzt nicht ganz was du machen möchtest. Du konsumierst ja den RESTService als String?! Was ist dein Problem?


----------



## mrBrown (9. Jul 2017)

Albus hat gesagt.:


> Auch mein Versuch den Header umszustellen scheitert leider.


Wie hast du es denn probiert und woran scheitert es?



Albus hat gesagt.:


> Hab Ihr mir einen Tipp?


Einen Bug melden, weil der Media-Type Unsinn ist. 
SCNR


----------



## Albus (10. Jul 2017)

Guten Morgen Flown, hallo Mister Brow,

vielen Dank for eure freundlichen Nachrichten.

@Flowen mein Problem ist das ich den Rest-API aufruf als String entgegennehme, und damit dann nicht weiß wie ich sinvoll weiterarbeite. In der Regel habe ich eine Anfrage Klasse "Quote":

Quote quote = restTemplate.getForObject(
        "https://itis.gov/ITISWebService/jsonservice/getFullHierarchyFromTSN?tsn=558090", Quote.class);
log.info(quote.toString());

deren Attribute werden dann mit den Werten aus dem Json-Objekt belget, mit dieser Quote-Klasse kann ich dann Sinvoll weiter arbeiten.

@mrBrown

Mein Versuch den Header anderst du lesen war folgender, welchen ich schon oben beschriben habe.

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity entity = new HttpEntity( headers);
ResponseEntity<String> result = restTemplate.exchange("https://itis.gov/ITISWebService/jsonservice/getFullRecordFromTSN?tsn=202384",HttpMethod.GET, entity, String.class);
log.info(result.getBody());

Ich danke euch für eure Hilfe 

Freundliche Grüße
Jörg


----------



## Flown (10. Jul 2017)

Albus hat gesagt.:


> @Flowen mein Problem ist das ich den Rest-API aufruf als String entgegennehme, und damit dann nicht weiß wie ich sinvoll weiterarbeite. In der Regel habe ich eine Anfrage Klasse "Quote":
> 
> Quote quote = restTemplate.getForObject(
> "https://itis.gov/ITISWebService/jsonservice/getFullHierarchyFromTSN?tsn=558090", Quote.class);
> ...


Und deine Klasse ist auch richtig annotiert und/oder hat die richtigen Namen aus den key-value pairs des JSON?

Wie ich sehe gehts auch über einen SOAP (xml) Webservice, warum machst du denn das nicht mit dem, da kannst du dir den Client bauen lassen (WSDL)?


----------



## Albus (10. Jul 2017)

Hallo Flown,

vielen Dank für deine schnelle Antwort,

Meine Quote-Klasse habe ich wiefolgt gebaut,

```
@JsonIgnoreProperties(ignoreUnknown = true)
public class Quote {

    private String tsn;

    public Quote() {
    }

    public String getTsn() {
        return tsn;
    }

    public void setTsn(String tsn) {
        this.tsn = tsn;
    }

    @Override
    public String toString() {
        return "Der Suchbegriff " +tsn + " liefert "  +" Ergebnisse \n";
    }
}
```
Zu Test-Zwecken versuche ich erstmal nur ein Attribut zu erfragen. Das klappt mit anderen Apis recht gut.

SOAP ist tatsächlich eine Möglichkeit, ich habe das mal halbherzig versucht was auf anhieb Leider auch nicht geklappt hat. Jedoch werd ich mit die Möglichkeit genauer anschauen müssen wenn es über REST nich Möglich ist.

Liebe Grüße
Albus


----------



## Flown (10. Jul 2017)

Bitte verwende Code-Tags [code=java]//JAVA CODE HERE[/code] wenn du hier code postest.

Ich kann dir jetzt in der Arbeit leider nicht helfen, da ich keine STS hier habe, aber ich nehme mal an, dass das Problem bei den multiplen "tsn" liegt.


----------



## mrBrown (10. Jul 2017)

Albus hat gesagt.:


> @mrBrown
> 
> Mein Versuch den Header anderst du lesen war folgender, welchen ich schon oben beschriben habe.
> 
> ...


Ich würde den Contenttype einfach mal auf Text/json setzen, statt auf application/json. Dazu kannst du den Konstruktor von MediaType nutzen, als Konstante gibts da leider nichts


----------



## Albus (10. Jul 2017)

Hallo Flown,



Flown hat gesagt.:


> Bitte verwende Code-Tags [code=java]//JAVA CODE HERE[/code] wenn du hier code postest.



Wird gemacht 

Jedoch liegt es leider nicht an den "tsn"- Attributen, da es auch nicht klappt wenn ich ein einzigartiges Attribut verweden. Es liegt glaube tatsächlich am Content-Type. 

Viele Grüße
Jörg


----------



## Albus (10. Jul 2017)

Hallo Mr. Brown,

vielen Dank für diesen Ansatz,

sowohl 

```
HttpHeaders headers = new HttpHeaders();
MediaType myMediaType = new MediaType("text/json");
headers.setContentType(myMediaType);
HttpEntity entity = new HttpEntity(headers);
ResponseEntity<String> result = restTemplate.exchange("https://itis.gov/ITISWebService/jsonservice/getFullRecordFromTSN?tsn=202384", HttpMethod.GET, entity, String.class);
log.info(result.getBody());
```

als auch 


```
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList("text/json"));
HttpEntity entity = new HttpEntity(headers);
ResponseEntity<String> result = restTemplate.exchange("https://itis.gov/ITISWebService/jsonservice/getFullRecordFromTSN?tsn=202384", HttpMethod.GET, entity, String.class);
log.info(result.getBody());
```

liefern leider keinen Erfolg.

Freundliche Grüße


----------



## mrBrown (10. Jul 2017)

Du solltest den richtigen Konstruktor nutzen: `new MediaType("text", "json")`


----------



## Albus (10. Jul 2017)

Ich habe den Code nun angepasst.


```
HttpHeaders headers = new HttpHeaders();
headers.setContentType(new MediaType("text", "json"));
HttpEntity entity = new HttpEntity( headers);
ResponseEntity<String> result = restTemplate.exchange("https://itis.gov/ITISWebService/jsonservice/getFullRecordFromTSN?tsn=202384", HttpMethod.GET, entity, String.class);
log.info(result.getBody());
```

Leider kein Erfolg


```
Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.
2017-07-10 16:40:51.776 ERROR 351168 --- [           main] o.s.boot.SpringApplication               : Application startup failed

java.lang.IllegalStateException: Failed to execute CommandLineRunner
   at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:779) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
   at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:760) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
   at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:747) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
   at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
   at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
   at org.springframework.boot.SpringApplication.run(SpringApplication.java:1151) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
   at com.example.demo.DemoApplication.main(DemoApplication.java:22) [classes/:na]
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_111]
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_111]
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_111]
   at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_111]
   at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147) [idea_rt.jar:na]
Caused by: org.springframework.web.client.HttpClientErrorException: 404 Not Found
   at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91) ~[spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
   at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:700) ~[spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
   at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:653) ~[spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
   at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:613) ~[spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
   at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:531) ~[spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
   at com.example.demo.DemoApplication.lambda$run$0(DemoApplication.java:60) [classes/:na]
   at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:776) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
   ... 11 common frames omitted

2017-07-10 16:40:51.778  INFO 351168 --- [           main] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@169cf: startup date [Mon Jul 10 16:40:50 CEST 2017]; root of context hierarchy
2017-07-10 16:40:51.778  INFO 351168 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans on shutdown
```


----------



## SeriousD0nkey (10. Jul 2017)

Was mir in deinem letzten Stacktrace ins Auge fällt ist, dass eine HttpClientErrorException geworfen wird welche den Status Code 404 hat. Vielleicht irre ich mich, aber wenn der Content-Type falsch wäre, würden dann nicht ein 406 geworfen?


----------



## thecain (10. Jul 2017)

So wie es aussieht behandelt die Website den Content-Type nicht richtig. Content-Type application/json bzw. text/json 404. Content-Type nichts, Antwort als json. Also am besten einfach mal nichts setzen.

Kannst du auch mit Postman oder einem ähnlichen Tool testen


----------



## Albus (10. Jul 2017)

Guten Abend SeriousD0nkey & thecain,

schön das Ihr euch an der Problemlösung beteiligt.

@thecain wenn ich dich richtig vertsteh empfiehlst du soll einen Aufruf.


```
Quote quote = restTemplate.getForObject(
        "http://www.itis.gov/ITISWebService/jsonservice/getFullRecordFromTSN?tsn=202384", Quote.class);
log.info(quote.toString());
```

Leider führt das zu einer NullPointerException

```
Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.
2017-07-10 19:21:59.332 ERROR 349956 --- [           main] o.s.boot.SpringApplication               : Application startup failed

java.lang.IllegalStateException: Failed to execute CommandLineRunner
   at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:779) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
   at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:760) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
   at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:747) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
   at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
   at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
   at org.springframework.boot.SpringApplication.run(SpringApplication.java:1151) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
   at com.example.demo.DemoApplication.main(DemoApplication.java:21) [classes/:na]
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_111]
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_111]
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_111]
   at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_111]
   at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147) [idea_rt.jar:na]
Caused by: java.lang.NullPointerException: null
   at com.example.demo.DemoApplication.lambda$run$0(DemoApplication.java:43) [classes/:na]
   at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:776) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
   ... 11 common frames omitted
```


----------



## mrBrown (10. Jul 2017)

Dann zeig doch mal die Zeile mit der NPE


----------



## Albus (10. Jul 2017)

Also ich dachte weil es in der vierten Zeile von untensteht


----------



## thecain (10. Jul 2017)

Ja, aber Zeile 43 ist interessant


----------



## Albus (11. Jul 2017)

Zeile 43 war zu diesem Zeitpunkt:

```
log.info(quote.toString());
```

Hier nochmal der gesamte Code

```
package com.example.demo;

import hello.Quote;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.http.*;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class DemoApplication {

    private static final Logger log = LoggerFactory.getLogger(DemoApplication.class);

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder) {
        return builder.build();
    }

    @Bean
    public CommandLineRunner run(RestTemplate restTemplate) throws Exception {
        return args -> {

//Funktioniert nicht, NullPointer
            Quote quote = restTemplate.getForObject(
                    "http://www.itis.gov/ITISWebService/jsonservice/getFullRecordFromTSN?tsn=202384", Quote.class);
            log.info(quote.toString());

//Werte liegen nur als String vor
            String quote = restTemplate.getForObject(
                    "http://www.itis.gov/ITISWebService/jsonservice/getFullRecordFromTSN?tsn=202384", String.class);
            log.info(quote.toString());

//Funktioniert nicht 404 error
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(new MediaType("text", "json"));
            HttpEntity entity = new HttpEntity( headers);
            ResponseEntity<String> result = restTemplate.exchange("http://itis.gov/ITISWebService/jsonservice/getFullRecordFromTSN?tsn=202384",HttpMethod.GET, entity, String.class);
            log.info(result.getBody());

//https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html
//https://itis.gov/web_service.html
        };
    }
}
```


----------

