hatenob

プログラムって分からないことだらけ

Wildfly 8でEJBとJAX-WSを同じインタフェースで呼ぶ

JAX-RSのServiceを、同じ「Service」として例えばJSFのManagedBeanから、EJBでもJAX-WSでも呼べるようにしてみた。
それ自体は別に難しいことではなかったです。

Serviceクラス

// for JAX-RS
@Path("todo")
// for JAX-WS
@WebService
// for EJB
@Stateless
@LocalBean
@Local(TodoServiceHome.ILocal.class)
@Remote(TodoServiceHome.IRemote.class)
// for CDI
@Named
public class TodoService implements TodoServiceHome {

    // for JAX-RS
    @PUT
    @Path("register")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    // for JAX-WS
    @WebMethod
    public Result register(TodoParam param) {
        ...
    }
    ...
}

それ自体に@Pathを付けてJAX-RSにし、SLSBにして、WebServiceにする、というだけ。
でもEJBは@Statelessだけではなぜかダメで、@LocalBeanを付けないとダメだった。@LocalBeanを付けないといけないケースは、こんな感じ。ソースを追いかけるまではしてないので、何かお作法が足りなかったのかもしれないけれど。

  • @Stateless単独 → @LocalBean不要
  • @Stateless + @Path(JAX-RS) → @LocalBean不要
  • @Stateless + @WebService → @LocalBean必要

ServiceHomeインタフェース

一応リモートからも呼べるようにということで、インタフェースを用意してあります。

@WebService
public interface TodoServiceHome {
    @WebMethod
    Result register(TodoParam param);

    @WebMethod
    List<Todo> findAll();

    @WebMethod
    Result remove(String id);

    @Local
    public interface ILocal extends TodoServiceHome {
    }

    @Remote
    public interface IRemote extends TodoServiceHome {
    }
}

内部でインタフェース定義してるのはローカルとリモートの2つを使うときでもimplementsに書くのを1つで済ますためのものです。

実行

あとはこれを中から呼ぶときはEJBコール、外から呼ぶときはJAX-WSクライアントで呼び出すなりすればOKです。1つのサービスを異なるプロトコルで呼び出すことができます。
中か外かを意識したくないようなときは、とりあえずEJBのつもりでインジェクションするかJNDIからlookupして、ダメならJAX-WSクライアントを使うとかでいけそうな気がする。