私が持っているのは、メッセージの種類を表す一連の 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 マジックを使用する必要がありますか?
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;
今朝私が遭遇した問題の 1 つは、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;
}
マーシャリングとアンマーシャリングは期待どおりに機能し、永続性はサブクラスのテーブルに対してです (スーパークラス テーブルはまったくありません)。
私は JTA に関する Blaise のメモを見ました。Message および REGMessage クラスを完全に元に戻した後、このミックスに取り込もうとするかもしれません。