2014-12-11 4 views
5

Mam problem z wykorzystaniem Spring's RestTemplate z modułem hateoas do tworzenia nowych powiązanych obiektów. Próbowałem już pobrać obiekt Foo i przypisać go do obiektu Bar, który próbuję utworzyć. Kiedy ogłaszam, że serwer daje mi HTPp 400 Bad Request. Kiedy próbowałem umieścić przedmiot zasobów z linkiem, mam ten wyjątek:Nie można wysłać nowej encji ze związkiem za pomocą RestTemplate i Spring Data REST

Exception in thread "main" org.springframework.web.client.RestClientException: Could not write request: no suitable HttpMessageConverter found for request type [org.springframework.hateoas.Resource] 

jestem ze stratą na zastanawianie się, jak stworzyć poprawne żądanie POST przy użyciu RestTemplate przeciwko służbie Wiosna danych REST.

Tło: Mam dwie klasy Foo i Bar. Foo ma OneToMany relacje z Barem, a więc Bar ma związek ManyToOne z Foo.

Kod dla każdej klasy jest następujący:

Foo:

package com.foo; 

//Imports omitted for clarity 

@Entity 
@Getter 
@Setter 
@Table(name="Foo", schema="dbo") 
public class Foo implements Identifiable<Integer> { 

    @Id 
    @Column(name="FOO_I") 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Integer id; 

    @Column(name="Name") 
    private String name; 

    @Column(name="descript") 
    private String description; 

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy="foo") 
    private Set<Bar> bars; 
} 

bar:

package com.foo; 

@Entity 
@Getter 
@Setter 
@Table(name="Bar", schema="dbo") 
public class Bar implements Identifiable<Integer> { 

    @Id 
    @Column(name="BAR_I") 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Integer id; 

    @Column(name="barname") 
    private String name; 

    @Column(name="bardescription") 
    private String description; 

    @Column(name="qty") 
    private int qty; 

    @ManyToOne 
    @JoinColumn(name="FOO_I", referencedColumnName="FOO_I", nullable=false) 
    private Foo foo; 
} 

Ja próbując odpowiedzieć na http://nonexistantdomain.com.mx.uk.ch:8080/bars aby utworzyć nowy pasek, który jest związane z foo którego FOO_I jest 1.

Widzę wyjście z rzeczy l ike http://nonexistantdomain.com.mx.uk.ch:8080/foos/1 i http://nonexistantdomain.com.mx.uk.ch:8080/foos/1/bars i http://nonexistantdomain.com.mx.uk.ch:8080/bars/5. Wiem więc, że związki działają.

Dalej jestem w stanie utworzyć nowy pasek używając wget i następujące pocztowy ciało http://nonexistantdomain.com.mx.uk.ch:8080/bars/:

{ 
    "name": "newWgetBar", 
    "description": "just another bar", 
    "qty": 2, 
    "foo" : "http://nonexistantdomain.com.mx.uk.ch:8080/foos/1" 
} 

Który działa skutecznie. Jak mogę użyć Spring's RestTemplate, aby to zrobić, abym mógł osiągnąć to, czego potrzebuję z mojego kodu Java?

Edytuj:

Oto przykłady, których próbowałem.

private RestTemplate acquireTemplate(boolean isHalJson) { 
    ObjectMapper mapper = new ObjectMapper();      
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 
    mapper.registerModule(new Jackson2HalModule()); 
    mapper.registerModule(new JodaModule());   

    MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); 
    converter.setSupportedMediaTypes(MediaType.parseMediaTypes("application/hal+json")); 
    converter.setObjectMapper(mapper); 

    return new RestTemplate(Collections.<HttpMessageConverter<?>> singletonList(converter)); 
} 

public void addABar(String name) { 
    Bar b = new Bar(); 
    b.setName(name); 
    b.setDescription("An added bar."); 
    b.setQty(2); 
    RestTemplate template = acquireTemplate(); 
    ResponseEntity<Foo> f = template.getForEntity("http://localhost:8080/foos/1", Foo.class); 
    Link l = new Link("foo","http://localhost:8080/foos/1"); 
    Resource<Bar> r = new Resource<Bar>(b,l);  
    URI i = template.postForLocation("http://localhost:8080/bars", r); 
} 

public void addABarAttempt2(String name) { 
    Bar b = new Bar(); 
    b.setName(name); 
    b.setDescription("An added bar."); 
    b.setQty(2); 
    RestTemplate template = acquireTemplate(); 
    ResponseEntity<Foo> f = template.getForEntity("http://localhost:8080/foos/1", Foo.class); 
    b.setFoo(f.getBody()); 
    URI i = template.postForLocation("http://localhost:8080/bars", b); 
} 

public void addABarAttempt3(String name) { 
    Bar b = new Bar(); 
    b.setName(name); 
    b.setDescription("An added bar."); 
    b.setQty(2); 
    RestTemplate template = acquireTemplate(); 
    template.put("http://localhost:8080/foos/1/bars",b); 
} 

Wszystkie trzy przykłady kończą się niepowodzeniem z różnych powodów.

+0

Zobaczymy, czy rozumiem pytanie, nie można utworzyć nowy Publikuj instancję, która ma pożądany zestaw "Foo". Jeśli nie możesz utworzyć nowego paska, dlaczego możesz zobaczyć relacje i obiekt paska? Jeśli nie możesz utworzyć nowego pręta, to nie powinno być obiektu z paskiem? – hofan41

+0

Jak tworzysz tę wiadomość? JavaScript? – yunandtidus

+0

Proszę podać pełny ślad stosu + kod klienta java (który próbuje utworzyć pasek) –

Odpowiedz

2

Co o użyciu tego kodu:

 RestTemplate restTemplate = new RestTemplate(); 
     restTemplate.getMessageConverters().add(new MappingJacksonHttpMessageConverter()); 
     restTemplate.getMessageConverters().add(new StringHttpMessageConverter()); 

     String uri = new String("url"); 

     Bar b= new Bar(); 
     bar.setName("newWgetBar"); 

     rt.postForObject(uri, b, Bar.class); 

byłoby przydatne, jeśli pokażesz nam, co masz na zaprogramować tak daleko na RestTemplate