Jakarta EE StarterでJava EE/Jakarta EEを始める

最近のフレームワークにはナントカStarterが用意されていて、簡単に最初のプロジェクトを作れるようになっています。
Java EE/Jakarta EEの場合、コンテナを起動してデプロイするという2段階だったりして、最初に動かすところまでが大変でした。

そういう問題に対処するために、Eclipse starter for Jakarta EEが用意されました。
https://start.jakarta.ee/

他のstarterと違って、Webでいろいろ選んで初期ファイルを構成するのではなく、単なるMavenArchetypeです。

mvn archetype:generate -DarchetypeGroupId="org.eclipse.starter" -DarchetypeArtifactId="jakarta-starter" -DarchetypeVersion="1.0.0"

実行はこんな感じ・・・

mvn clean package payara-micro:start

しかしテストでこけるので、テストを飛ばしましょう。
f:id:nowokay:20220418104644p:plain

-DskipTests=trueをつけて実行します。

mvn clean package payara-micro:start -DskipTests=true

準備が整うまで結構時間がかかります。REST Endpointsの表示が出たら準備完了。
f:id:nowokay:20220418110922p:plain

localhost:8080に接続すると次のようになります。
f:id:nowokay:20220418104854p:plain

ソースコードとしてはJAX-RSのエンドポイントとしてCafeResource.javaJPAのエンティティとしてCoffee.java、クエリーを投げるレポジトリとしてCafeRepository.javaができています。 f:id:nowokay:20220418111507p:plain

CafeResource.javaはこんな感じ

@Path("coffees")
public class CafeResource {

    @Inject
    private CafeRepository cafeRepository;

    @GET
    @Produces({ MediaType.APPLICATION_JSON })
    public List<Coffee> getAllCoffees() {
        return this.cafeRepository.getAllCoffees();
    }

    @POST
    @Consumes({ MediaType.APPLICATION_JSON })
    public Coffee createCoffee(Coffee coffee) {
        try {
            return this.cafeRepository.persistCoffee(coffee);
        } catch (PersistenceException e) {
        ....

Coffee.javaはこんな感じ

@Entity
@NamedQuery(name = "findAllCoffees", query = "SELECT o FROM Coffee o ORDER BY o.name")
public class Coffee implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotBlank(message = "Name cannot be blank.")
    protected String name;

    @NotNull(message = "Price must be set.")
    @PositiveOrZero(message = "Price must be greater than or equal to zero.")
    protected Double price;
        ...

CafeRepository.javaはこんな感じ

@Stateless
public class CafeRepository {

    @PersistenceContext
    private EntityManager entityManager;

    public List<Coffee> getAllCoffees() {
        logger.log(Level.INFO, "Finding all coffees.");

        return this.entityManager.createNamedQuery("findAllCoffees", Coffee.class).getResultList();
    }

    public Coffee persistCoffee(Coffee coffee) {
        logger.log(Level.INFO, "Persisting the new coffee {0}.", coffee);
        this.entityManager.persist(coffee);
        return coffee;
    }

サーブレットも動かせます。

@WebServlet(urlPatterns = "/NewServlet")
public class NewServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        try ( PrintWriter out = response.getWriter()) {
            out.println("""
                        <!DOCTYPE html>
                        <html><head>
                        <title>Servlet NewServlet</title>
                        </head>
                        <body>
                        <h1>Servlet NewServlet at %s</h1>
                        %s
                        </body></html>
                        """.formatted(request.getContextPath(), LocalDateTime.now()));
        }
    }

}

f:id:nowokay:20220418113923p:plain

ということで、Java EE / Jakarta EEでなにか作るぞっていう場合の足掛かりになるようになっていますね。