我所拥有的是一组表示消息类型的Java类(接近25个)。它们都继承自我想要抽象的Message类。每种消息类型都会在Message超类提供的集合中添加一些额外的字段。
我正在使用RESTeasy实现一些RESTful Web服务,并希望有这样的方法:
public Response persist(Message msg) {
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
em.persist(msg);
} catch (Exception e) {
e.printStackTrace();
}
tx.commit();
em.close();
return Response.created(URI.create("/message/" + msg.getId())).build();
}
而不是具有25个单独的持久化方法,每个方法都针对特定的消息类型进行了定制。
目前,我已经注释了我的Message类:
@MappedSuperclass
@XmlRootElement(name = "message")
public abstract class Message implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
Integer id;
@Embedded
Header header;
@Embedded
SubHeader subHeader;
我的子类看起来像这样:
@Entity
@XmlRootElement(name="regmessage")
@XmlAccessorType(XmlAccessType.FIELD)
public class REGMessage extends Message {
@XmlElement(required = true)
int statusUpdateRate;
@XmlElement(required = true)
int networkRegistrationFlag;
这会创建一个看起来的模式,就像它应该工作一样,但是在持久化操作期间在服务器端看到的所有模式都是一个Message对象(子类型完全丢失,或者至少它不是'编组回到其正确的子类型)。在客户端,要调用方法,我执行此操作:
REGMessage msg = new REGMessage();
// populate its fields
Response r = client.createMessage(msg);
我正在尝试什么?我需要使用什么JAXB魔术才能使翻译按照应有的方式发生 - 即,将Java中的所有内容视为一条消息,以保持方法数量的减少但仍然保留所有特定于子类型的信息?
感谢Blaise的博客指点,现在看起来它正处于完全工作的道路上。这就是我所拥有的,它确实有效:
//JAXB annotations
@XmlRootElement(name="message")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso(REGMessage.class)
//JPA annotations
@MappedSuperclass
public class Message {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@XmlAttribute
private Integer id;
private JICDHeader header;
private int subheader;
@XmlAnyElement
@Transient
private Object body;
我今天早上遇到的一个问题是来自Hibernate的关于列数不匹配的一个神秘错误。一旦我意识到“身体”被映射到表格中,我就将其标记为瞬态而且瞧瞧!
@XmlRootElement(name="regmessage")
@XmlAccessorType(XmlAccessType.FIELD)
@Entity
public class REGMessage extends Message {
private int field1;
private int field2;
现在,此代码生成的唯一表是regmessage表。在RESTeasy方面:
@Path("/messages")
public class MessageResource implements IMessageResource {
private EntityManagerFactory emf;
private EntityManager em;
Logger logger = LoggerFactory.getLogger(MessageResource.class);
public MessageResource() {
try {
emf = Persistence.createEntityManagerFactory("shepherd");
em = emf.createEntityManager();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
@POST
@Consumes("application/xml")
public Response saveMessage(Message msg) {
System.out.println(msg.toString());
logger.info("starting saveMessage");
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
em.persist(msg);
} catch (Exception e) {
e.printStackTrace();
}
tx.commit();
em.close();
logger.info("ending saveMessage");
return Response.created(URI.create("/message/" + msg.getId())).build();
}
}
这实现了一个接口:
@Path("/messages")
public interface IMessageResource {
@GET
@Produces("application/xml")
@Path("{id}")
public Message getMessage(@PathParam("id") int id);
@POST
@Consumes("application/xml")
public Response saveMessage(Message msg) throws URISyntaxException;
}
编组&按预期解组工作,持久化是子类的表(并且根本没有超类表)。
我确实看到了Blaise关于JTA的说明,在我完成对Message&amp ;;的充实之后,我可能会尝试将其添加到这个混音中。 REGMessage类完全退出。
答案 0 :(得分:8)
您是否尝试将以下内容添加到邮件类中? @XmlSeeAlso注释将让JAXBContext知道子类。
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSeeAlso;
@XmlRootElement
@XmlSeeAlso(RegMessage.class)
public abstract class Message {
Integer id;
}
替代策略:
以下是我帮助人们使用的策略的链接:
基本上,您有一个消息对象和多个单独的消息有效负载。消息和有效负载之间的关系通过@XmlAnyElement注释来处理。
有关交易处理的说明
我注意到您正在处理自己的交易。您是否考虑将JAX-RS服务实现为会话bean并利用JTA进行事务处理?有关示例,请参阅: