I'm struggling on how to use Spring's RestTemplate with the hateoas module to create new related entities. I've tried fetching a Foo object and assigning it to the Bar object I'm trying to create. When I post that the server gives me a Http 400 Bad Request. When I tried to post a Resource object with a link, I get this exception:
Exception in thread "main" org.springframework.web.client.RestClientException: Could not write request: no suitable HttpMessageConverter found for request type [org.springframework.hateoas.Resource]
I'm at a loss for figuring out how to create the correct POST request using RestTemplate against a Spring Data REST service.
Background: I have two classes Foo and Bar. Foo has a OneToMany relationship with Bar and thus Bar has a ManyToOne relationship with Foo.
The code for each class is as follows:
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;
}
I'm attempting to post to http://nonexistantdomain.com.mx.uk.ch:8080/bars to create a new bar that is related to a foo whose FOO_I is 1.
I can see output from things like http://nonexistantdomain.com.mx.uk.ch:8080/foos/1 and http://nonexistantdomain.com.mx.uk.ch:8080/foos/1/bars and http://nonexistantdomain.com.mx.uk.ch:8080/bars/5. So I know the relationships are working.
Further I'm able to create a new bar using wget and the following post body to 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"
}
Which works successfully. How can I use Spring's RestTemplate to do this so I can accomplish what I need from my java code?
Edit:
Here are the examples I have tried.
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);
}
All three examples fail for differing reasons.
What about use this code:
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);
it would be usefull if you show us what do you program so far on your RestTemplate
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With