10

私が持っているのは、メッセージの種類を表す一連の 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 クラスを完全に元に戻した後、このミックスに取り込もうとするかもしれません。

4

1 に答える 1

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;

}

別の戦略:

これは、私が人々の使用を支援した戦略へのリンクです。

基本的に、1 つのメッセージ オブジェクトと複数の個別のメッセージ ペイロードがあります。メッセージとペイロードの関係は、@XmlAnyElement アノテーションによって処理されます。

お取引に関するご注意

独自のトランザクションを処理していることに気付きました。JAX-RS サービスをセッション Bean として実装し、JTA をトランザクション処理に活用することを検討しましたか? 例については、次を参照してください。

于 2010-09-29T13:20:57.967 に答える