Home > Software design >  How can I return an object from a POST method with Spring Boot?
How can I return an object from a POST method with Spring Boot?

Time:11-23

I'm trying to create a communication between two services with Spring Boot, and I'm failing to return a custom object from a POST.

I have tried something like

1st service:

@RestController
@RequestMapping("/broker")
class HostController{
    @PostMapping(value = "/bid")
    public Bid bid(@RequestBody Auction auction){
        return new Bid(new URI("http://url:8080"));
    }
}

2nd service:

ResponseEntity<Bid> response = rest.postForEntity(hostURL   "/bid", auction, Bid.class);
response.getBody();

The problem is I get an error message saying "cannot deserialize from Object value" for the Bid class, which makes me think the Auction is being sent but the Bid isn't sent back.

I'm also not sure how the serialization happens for the auction, as I only put the "@RequestBody" and it started working. The Auction class even has a Bid object inside, but that doesn't seem to be a problem.

class Bid{
    private URI host;
    
    public Bid(URI host){ this.host = host; }

    public URI getHost() { return host; }
}

class Auction{
    URI host;

    private Bid winner; //Not defined when the problem happens

    public Auction(URI host){ this.host = host; }
    
    public URI getHost(){ return host; }
}

The full stack trace is gigantic, but the part I think is relevant is this:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.gustavovbs.microservicesoffloading.Bid` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)\n at [Source: (PushbackInputStream); line: 1, column: 2]\n\tat
 
com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)\n\tat
 com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1764)\n\tat
 com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:400)\n\tat

com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1209)\n\tat
 com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1415)\n\tat
 com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:362)\n\tat
 com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:195)\n\tat
 com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:322)\n\tat
 com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4593)\n\tat
 com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3601)\n\tat
 org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:378)\n\t... 63 more\n","message":"Type definition error: [simple type, class com.gustavovbs.microservicesoffloading.Bid]; 

nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.gustavovbs.microservicesoffloading.Bid` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)\n at [Source: (PushbackInputStream); line: 1, column: 2]","path":"/broker/broadcast"}"

CodePudding user response:

When you transfer some stuff, make sure its serializable and also dont forget to add no arg constructor. This should work.

   class Bid implements Serializable {
    
    private URI host;

    public Bid();

    public URI getHost() {
        return host;
    }

    public void setHost(URI host) {
        this.host = host;
    }
}

CodePudding user response:

Please try with adding @ResponseBody annotation to your Controller method bid. After doing this your HTTP response will have body with JSON representation of your object so it should be possible to serialize that back in your postForEntity.

@PostMapping(value = "/bid")
@ResponseBody
public Bid bid(@RequestBody Auction auction){
    return new Bid();
}

For more information check below link:

How does the Spring @ResponseBody annotation work?

CodePudding user response:

I managed to make it work just by adding the default constructor to the Bid class, as discussed in the comments.

class Bid{
    private URI host;

    public Bid(){}
    
    public Bid(URI host){ this.host = host; }

    public URI getHost() { return host; }
}
  • Related