9

I am getting the below error message while getting the user entity from the openfire rest api. ( I am wrapping the my Api Endpoints with openfire Restapi Endpoints.)

"error": "Internal Server Error", "exception": "org.springframework.http.converter.HttpMessageNotWritableException", "message": "Could not write JSON: No serializer found for class java.io.ByteArrayInputStream and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS); nested exception is com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class java.io.ByteArrayInputStream and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: com.mashape.unirest.http.HttpResponse[\"rawBody\"])", "path": "/usersInfo/user2"

The code is the following.

String  host ="http://abdul01anpi01:9090" ;
String userEndPoint = "/plugins/restapi/v1/users" ;
String apiURL = host+userEndPoint ;
HttpResponse<JsonNode> response =null;

response = Unirest.get(apiURL +"/{username}").header("accept", "application/json").header("Content-Type", "application/json").routeParam("username",String.valueOf(username)).asJson();

The expected output from the response is the following.

{
    "username": "user2",
    "name": "user2",
    "properties": null
}

Kindly advise, any help is appreciated.

Pengyy
  • 37,383
  • 15
  • 83
  • 73
abdul
  • 101
  • 1
  • 1
  • 3
  • Hope the username you're passing as a routeParam isn't null? – cdaiga Sep 14 '17 at 09:44
  • No. I am passing the username – abdul Sep 14 '17 at 11:36
  • 5
    @Bean public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() { ObjectMapper mapper = new ObjectMapper(); mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(mapper); return converter; } – abdul Sep 14 '17 at 14:51
  • This solved the my issue . – abdul Sep 14 '17 at 14:51
  • You are free to answer your own question. – cdaiga Sep 14 '17 at 17:16

3 Answers3

7

The poster found a solution and posted it in a comment. Since it's been a few years, I figured it might be worth copying as an actual answer:

@Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
    ObjectMapper mapper = new ObjectMapper();
    mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
    MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(mapper);
    return converter;
}

Let me add the description for the flag that is being set to false :

/**
 * Feature that determines what happens when no accessors are
 * found for a type (and there are no annotations to indicate
 * it is meant to be serialized). If enabled (default), an
 * exception is thrown to indicate these as non-serializable
 * types; if disabled, they are serialized as empty Objects,
 * i.e. without any properties.
 *<p>
 * Note that empty types that this feature has only effect on
 * those "empty" beans that do not have any recognized annotations
 * (like <code>@JsonSerialize</code>): ones that do have annotations
 * do not result in an exception being thrown.
 *<p>
 * Feature is enabled by default.
 */
FAIL_ON_EMPTY_BEANS
payne
  • 4,691
  • 8
  • 37
  • 85
1

it works, add a ResourceHttpMessageConverter!

@Configuration
public class EirExceptionConfig extends WebMvcConfigurerAdapter {
    @Autowired
    ObjectMapper objectMapper;

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(EirException.class, new EirExceptionJackson2Serializer());
        objectMapper.registerModule(simpleModule);
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(objectMapper);
        converters.add(new ResourceHttpMessageConverter());
        converters.add(converter);
    }
}
疯子Max
  • 11
  • 3
-1

Another way to solve this issue is to ignore the property which has return type of ByteArrayInputStream, for example you could decorate this class:

class Frodo {
    private bytes[] value;
    public Frodo(bytes[] value) {
        this.value = value;
    }

    public ByteArrayInputStream getFoo() throws IOException {
        return new ByteArrayInputStream(value());
    }

    public void setFoo(ByteArrayInputStream streamData) {
        // set value from streamData
    }
}

like this:

@JsonIgnoreProperties(value = { "foo" })
class Frodo {
    private bytes[] value;
    public Frodo(bytes[] value) {
        this.value = value;
    }

    public ByteArrayInputStream getFoo() throws IOException {
        return new ByteArrayInputStream(value());
    }

    public void setFoo(ByteArrayInputStream streamData) {
        // set value from streamData
    }
}

you can also ignore multiple properties: @JsonIgnoreProperties(value = { "foo", "anotherValue" })

Benas
  • 2,106
  • 2
  • 39
  • 66
  • can you please explain what is wrong with this approach? In backend you want to operate with byte streams, in frontend not so much. Using this approach you don't break your API in backend and can use byte streams, while at the same time you can marshall this class object to the Frontend, this looks like WIN-WIN for me – Benas Mar 08 '19 at 19:27