java - mvc - Jackson 2 y Spring Autowired Bean
spring security example (2)
He encontrado un problema con la serialización Jackson para mi objeto Usuario. Hay algunos campos privados con getters y setters. Y todo funciona bien cuando hago algo como esto:
public String json() {
MyUser user = new MyUser();
user.setUsername("myName");
return mapper.writeValueAsString(user); // Valid JSON
}
Pero me gustaría conectar automáticamente el objeto User con Spring Framework:
@Autowired
private MyUser user;
public String json() {
System.out.println(user.getUsername()); // Property set before and it works
return mapper.writeValueAsString(user); // Error
}
Y esto no funciona Tengo un error:
com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class org.apache.juli.OneLineFormatter and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: com.piggymetrics.classes.PiggyUser$$EnhancerBySpringCGLIB$$5f23855e["targetSource"]->org.springframework.aop.target.SimpleBeanTargetSource["beanFactory"]->org.springframework.beans.factory.support.DefaultListableBeanFactory["parentBeanFactory"]->org.springframework.beans.factory.support.DefaultListableBeanFactory["beanClassLoader"]->org.apache.catalina.loader.WebappClassLoader["resources"]->org.apache.catalina.webresources.StandardRoot["context"]->org.apache.catalina.core.StandardContext["logger"]->org.apache.juli.logging.DirectJDKLog["logger"]->java.util.logging.Logger["parent"]->java.util.logging.Logger["handlers"]->org.apache.juli.AsyncFileHandler["formatter"])
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:59)
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:26)
Y cuando trato de ignorar estos errores desconocidos
mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
Tengo una recursión infinita:
com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: org.apache.catalina.core.StandardEngineValve["container"]->org.apache.catalina.core.StandardEngine["pipeline"]->org.apache.catalina.core.StandardPipeline["basic"]->org.apache.catalina.core.StandardEngineValve["container"]
...
Parece que Spring hizo algo mal con la instancia de MyUser autocableada para que Jackson no pueda serializarlo.
¿Hay alguna forma de arreglarlo?
ACTUALIZAR
Mi clase de usuario es bastante simple:
package com.metrics.classes;
import com.metrics.classes.interfaces.User;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Component;
@Component
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class MyUser implements User {
private String username;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
Dado que usa MyUser
como un bean gestionado Spring, Spring ajusta su objeto a un proxy, por lo que cuando llama a mapper.writeValueAsString(user);
en realidad estás pasando un proxy como argumento. Dicho proxy contiene algunas propiedades que el asignador no puede serializar.
Puede intentar aplicar el filtro antes de la serialización para incluir solo las propiedades que necesita:
ObjectMapper mapper = new ObjectMapper();
SimpleFilterProvider simpleFilterProvider = new SimpleFilterProvider()
.addFilter("myUser", simpleBeanPropertyFilter.filterOutAllExcept("username"));
mapper.setFilters(filterProvider);
return mapper.writeValueAsString(user);
Esta excepción se UnknownSerializer
en la clase UnknownSerializer
. Aquí está el código exacto que arroja la excepción:
throw new JsonMappingException("No serializer found for class "+value.getClass().getName()
+" and no properties discovered to create BeanSerializer
(to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) )");
El mensaje de error agrega el nombre de la clase que no puede serializar. En su caso, según el mensaje de error, el problema es con la clase org.apache.juli.OneLineFormatter
. Por lo tanto, no hay problema con la clase MyUser
.
Ahora viene a razonar este error, se lanza al serializar una entidad que tiene todos los campos privados. En la clase org.apache.juli.OneLineFormatter
, todos los campos son privados sin ningún método public getter and setter.