我正在构建一个使用JPA(EclipseLink)提供JAX-RS REST服务的应用程序。当通过JSON公开用户实体时,我在某些字段(例如密码字段)上使用@XmlTransient
注释来将它们隐藏在JSON表示中。发送创建或更新(POST / PUT)操作时,我想再次填充缺少的字段,以便JPA正确执行操作。
我目前的做法是,我有一个自定义JsonDeserializer
,用于反序列化用户并添加缺少的字段。为此,我想注入(使用@Inject
)一个UserFacadeREST
bean处理JPA的东西。但是,此注入失败,bean实例为null
(当然会导致NullPointerException
)。
我的UserFacadeREST
bean的注释如下:
@Stateless
@LocalBean
@Path(UserFacadeREST.PATH)
public class UserFacadeREST extends AbstractFacade<User> {
//...
}
我的UserDeserilizer
(自定义JsonDeserializer
):
public class UserDeserializer extends JsonDeserializer<User> {
@Inject
private UserFacadeREST userFacade;
@Override
public User deserialize(JsonParser parser, DeserializationContext context) throws IOException,
JsonProcessingException {
JsonNode node = parser.getCodec().readTree(parser);
int userId = (Integer) ((IntNode) node.get("userID")).numberValue();
System.out.println(userId);
User user = userFacade.find(userId); // This line produces the NullPointerException
return user;
}
}
然后我在我的用户实体上使用@JsonDeserialize
:
@Entity
@Table(name = "User")
@XmlRootElement
@JsonDeserialize(using = UserDeserializer.class)
public class User implements Serializable {
// ...
}
我在我的WEB-INF文件夹中包含了一个bean.xml文件,bean-discovery-mode
设置为all
。我错过了什么?
答案 0 :(得分:3)
javax.enterprise.inject.spi.CDI.current().select(UserFacadeRest.class).get()
以编程方式注入bean,如Jon提到的问题的accepted answer或因此,对于我的问题,解决方案如下所示:
1
import javax.enterprise.inject.spi.CDI;
public class UserDeserializer extends JsonDeserializer<User> {
private final UserFacadeREST userFacade =
CDI.current().select(UserFacadeREST.class).get();
// Rest as before
}
2。在这种情况下,在我deserialize
的{{1}}方法中,我将构建一个只保存userID的用户。在每个请求方法中,我都必须检查所有用户,并通过调用JsonDeserializer
由实际用户替换它们。这意味着更多的业务逻辑工作,因为您必须记住,每当您需要在请求方法中处理EntityManager.find(User.class, user.getUserID())
时,首先必须执行查询以获取“完整”{{1}对象。在第一个解决方案中,此查询对业务逻辑是隐藏的,并且已经在User
。
User
答案 1 :(得分:1)
我对CDI并不是很熟悉,但是一些快速的Google会让我相信bean-discovery-mode
应该是all
,annotated
或none
( true
不是有效值。 Reference
如果没有解决问题,可能是Spring会遇到的问题:你必须将UserDeserializer
声明为bean,以便应用依赖注入。
编辑:刚发现这个other question基本上与您遇到的问题相同。
最终,您可能需要重新设计逻辑以在反序列化后调用userFacade
。