Kohei Nozaki's blog 

Entries tagged [javaee]

In-container JMS consumer/producer example


Posted on Saturday May 14, 2016 at 11:06PM in Technology


In this entry, I’ll show you a complete example of using JMS in a Java EE 7 compliant application container, through creating a webapp which consists of both a consumer and a producer. we’re going to deploy it to a container (WildFly 10.0.0.Final) and see a webapp produces and consumes a message.

Launch the container

Launch WildFly server with the following parameter so the bundled message queue broker (ActiveMQ Artemis) will be launched:

./standalone.sh -c standalone-full.xml

For IntelliJ IDEA, check how to launch WildFly with -c standalone-full.xml from this SO: http://stackoverflow.com/questions/25849810/how-to-run-wildfly-with-standalone-full-xml-from-intellij-idea

Define a queue

Launch jboss-cli and define a queue with this command:

jms-queue add --queue-address=testQueue --entries=queue/test,java:jboss/exported/jms/queue/test

Check if it’s successfully created:

[standalone@localhost:9990 /] /subsystem=messaging-activemq/server=default/jms-queue=testQueue:read-resource
{
    "outcome" => "success",
    "result" => {
        "durable" => true,
        "entries" => [
            "queue/test",
            "java:jboss/exported/jms/queue/test"
        ],
        "legacy-entries" => undefined,
        "selector" => undefined
    }
}

Create the webapp which contains consumer/producer

Here we’re going to create following three classes in the webapp:

  • MyProducer: a Stateless Session Bean which produces a message to the queue

  • MyConsumer: a Message-Driven Bean which consumes any messages being sent to the queue

  • MyServlet: Receives HTTP GET request and kicks MyProducer

The whole project can be obtained from My GitHub repository.

MyProducer

@Stateless
@LocalBean
public class MyProducer {

    @Resource(mappedName = "java:/queue/test")
    Queue testQueue;
    @Inject
    JMSContext jmsContext;

    public void enqueue(final String text) {
        jmsContext.createProducer().send(testQueue, text);
    }
}

MyConsumer

@MessageDriven(name = "MyMDB", activationConfig = {
        @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/test"),
        @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
        @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge")})
public class MyConsumer implements MessageListener {

    private final static Logger LOGGER = Logger.getLogger(MyConsumer.class.toString());

    @Override
    public void onMessage(final Message msg) {
        if (msg instanceof TextMessage) {
            try {
                final String text = ((TextMessage) msg).getText();
                LOGGER.info(() -> "Received: " + text);
            } catch (final JMSException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

MyServlet

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

    @EJB
    MyProducer myProducer;

    @Override
    protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
        final String text = "Hello, JMS!";
        myProducer.enqueue(text);
        resp.getWriter().write("Published! check output of the consumer: " + text + "\n");
    }
}

Of course you don’t need to put MyConsumer to the webapp which contains MyProducer. this is just an example, and in fact, just for asynchronous/background processing in a webapp, you better use more simple EJB Asynchronous methods or ManagedExecutorService instead of JMS. for real use-case, you may create a dedicated app for queue consumers and place your MyConsumer equivalent into it.

Trigger producing and consuming

Deploy the app and submit HTTP GET request to it as follows.

$ curl http://localhost:8080/jms-example/

If it worked successfully, you’ll see following response from the Servlet:

Published! check output of the consumer: Hello, JMS!

Then check console/output/log of your application container. if the consumer worked successfully, you can see the output something like following:

13:55:18,168 INFO  [class jms.MyConsumer] (Thread-438 (ActiveMQ-client-global-threads-271921988)) Received: Hello, JMS!

Conclusion

As described above, thanks to JMS, we can develop a messaging app without tons of annoying, vendor-specific boilar plate code, in lean and simple semantics. there are no worries of maintaining logic of connection handling, polling loop and so forth in the application code.

And note that there are no use of vendor-specific classes - it uses only standardized API which comes from javaee-api. you may need to alter some portion of code when you deploy this example to other Java EE 7 compliant container such as GlassFish, WebLogic or WebSphere, but that should be few.


Java EE ブログエンジン Apache Roller のご紹介


Posted on Thursday Dec 03, 2015 at 08:00AM in Technology


このエントリは Java EE Advent Calendar 2015 の3日目(12月3日)の記事です.

自己紹介

業務ではJPA, JAX-RSなどを使っているソフトウェアエンジニアです.趣味ではWildFly, JBatch, JSFなどを使っていろいろ作ったり,Java/Java EE関連OSSの不具合を見つけてパッチやPull Requestを送ったりしています.

今回紹介する Apache Roller のコミッタをやっているのですが,日本ではあまり知名度がないので,少しでも日本の方に興味を持ってもらえればと思い,紹介記事を書くことにしました.

Apache Rollerとは?

Apache Rollerは,Javaサーブレットコンテナ向けのオープンソースブログエンジンで,WordPressやMovable Typeとほぼ同じジャンルのソフトウェアです.元Sun Microsystemsのエンジニア David M. Johnsonさんによって2002年に作られ,blogs.sun.com(現 blogs.oracle.com )などで利用されてきました.

現在の最新バーションは,2015年3月にリリースされた5.1.2です.

誰が使っているの?

Rollerはさまざまな組織や個人によって使われています.組織での使用例としては,Javaエンジニアにはおなじみの Oracle blogs や, IBM developerworks blogApache Foundationのブログなどがあります.他にも世界中のさまざまな企業,官公庁などで使われています.

個人では,Java EEを追っかけている人にはおなじみの Adam Bienさん ,Javaの父 James Goslingさんなどが,Rollerを使ってブログを書いています. コミッタもそれぞれ自分でRollerのブログを持っています.

その他多数のユーザについては オフィシャルのWikiページにまとめられています.

使われている技術

DIコンテナとしてはGuiceが使われていて,パーシステンス層ではEclipseLink,ビュー・コントローラ層はStruts2 + JSP + Servlet,ブログのデザインなどはVelocityテンプレートで書けるようになっています.認証まわりではSpring Security,全文検索エンジンとしてはLuceneが使われています.

ServletとJSPのコードが多く,今となってはちょっと時代遅れな感は否めませんが,ソースは全て公開されているので,Javaで書かれていてリアルに運用されているWebシステムのサンプルとして一つの参考になるかもしれません.

特徴

マルチユーザー・マルチブログに対応

1つのインストレーションで複数のブログ,ユーザを作ることができます.

各ユーザーには3種類の権限のうちいずれかを割り当てることができ,具体的には,エントリの下書きだけができるユーザ(Limited),エントリの投稿などはできるがブログやシステムの設定変更はできないユーザ(Author),全ての操作ができるユーザ(Admin)のうちいずれかをユーザごとに割り当てることができます.組織用ブログなどで,日常的にレビュープロセスを取り入れているようなケースで便利に使うことができます. LDAP認証に対応しているのも組織で使いやすいポイントです.

個人で使う場合でも,複数のブログをかんたんに作れるので,たとえば技術系エントリはこのブログ,趣味の旅行の話題はまた別のブログ,といった感じで使い分けることができます.もちろん,それぞれのブログのデザインやテンプレートはべつべつに管理できます.

さまざまなDB・アプリケーションサーバに対応

DBスキーマ生成用スクリプトとして,MySQL,PostgreSQL,Oracle,DB2,SQL Server,Derby,HSQLDB用のものが用意されています.ほとんどのユーザおよび開発メンバが使っているのはMySQLなので,特に理由がなければMySQL 5.6.x以降をおすすめします(次のリリースからは5.6.xより前のサポートがなくなる予定なので).個人的にはPostgreSQLを使っていて,このブログもPostgreSQLで動いています.

いわゆるサーブレットコンテナ向けに作られているので,TomcatやJettyをはじめ,JBoss(WildFly),GlassFishなどのJava EEコンテナにもデプロイできます.ほとんどのユーザはTomcatを使っているようですが,個人的にはWildFly(このブログ)やJBoss EWSにデプロイして使っています.

Javaでプラグインが書ける

最近のブログサービスでは,冗長なHTMLだけではなくMarkdownや「はてな記法」のような簡潔なシンタックスを使ってエントリを書けるものが多くでてきています.Rollerがデフォルトでサポートしているのは標準的なHTMLだけですが,プラグインを使うことで,そういったシンタックスを使ってブログエントリを書けるようになります.

個人的には, Asciidoctorjプラグインというものを作り AsciiDoc シンタックスを使って日常的にエントリを書いています(このエントリもそうです).他にも MarkdownJSPWiki プラグインなど,いくつかのプラグインが公開されており,別途インストールすることで利用できるようになります.

プラグインを書くのはとても簡単で,適用するプラグインはエントリごとにべつべつに設定できます.今後またなんらかの新たな記法が登場してそれを使いたくなったら,HTMLへの変換エンジンとRollerをつなぐ部分だけをプラグインとして書いてやれば,既存のエントリはそのままに新しい記法を使うことができるようになります.ブログエントリの記法の他にも,コメントの記法,コメント認証などもプラグインとして独自に追加することができるようになっています.

インストール

いわゆるオンプレミス環境へのインストール方法については,英語になりますが Wiki および オフィシャルのインストレーションガイド を参照してください.また OpenShift で運用することもできます(無料枠でも可能).詳細は,こちらも英語になりますが, このブログエントリを参照してください.

メンテナンスなど

まずバックアップですが,個人的にはPostgreSQLデータベースとRollerのデータファイル用ディレクトリをssh経由でバックアップするためのAntスクリプトを書いて,定期的にcronで実行しています.スクリプトは GitHubで公開しています.

他のブログエンジンからのデータ移行については,残念ながら確立されたやり方はまだ存在していませんが,WordPressのブログエクスポート形式であるWXR形式のファイルを取り込むためのツールを作っています.詳細は こちらをご確認ください.

また,SVNからのソース取得,ビルド,プラグインのインストール,自家製パッチ適用などを自動化するためのAntスクリプトを GitHub に置いてあります.

その他,運用ノウハウなどは このブログエントリ によくまとまっています.

最後に

日本語情報は少なめですが,最新リリースでは,実用上は日本語依存の問題というのは特にありません.

ただ,日本語ブログで使うと表示上の違和感があるところがいくつかあったり,メッセージの誤訳や不足,モバイル用テーマ・一部の利用者が少ないDBでのみ生じる細かいバグが残っています(詳細は JIRA を参照).SVN上の最新版では,そのうちのいくつかは修正ずみですので,可能な方はぜひ 開発中の最新版のソース をSVNからチェックアウトしてビルドしてみてください.mvn clean package でWARファイルが生成されます. 前述のAntスクリプト も併用されると便利かもしれません.

バグレポート・パッチはもちろん大歓迎です.なにか日本語まわりで質問などあれば,このエントリにコメントをつけていただいても結構です.Javaエンジニアで,自分のブログを持ちたいとお考えの方,ぜひRollerを試してみてください!

リファレンスなど

宣伝:求人のご案内

現在,私の勤務先 株式会社 L is B ではエンジニア・デザイナーを募集しています.主に direct というインスタントメッセージングサービスの開発と運用を行っている会社です.

会社所在地は東京(+徳島県に開発拠点があります)ですが,一部リモートワークも認められています.少しでも興味を持たれた方,ぜひ応募してみてください!


An example of Maven EAR project consists of an EJB interface, an EJB implementation and a WAR


Posted on Friday Mar 06, 2015 at 10:43PM in Maven


The project consists of following principal modules:

  • eartest-ejb-api: holds an EJB local interface named Hello. packaging=jar. no dependency.

  • eartest-ejb-impl: holds an EJB implementation named HelloImpl which implements Hello. packaging=ejb. depends on eartest-ejb-api.

  • eartest-war: holds an Servlet which has an injection point of Hello interface. depends on eartest-ejb-api.

  • eartest-ear: holds above 3 modules in the EAR.

Whole project is can be obtained from https://github.com/lbtc-xxx/eartest .

Structure of eartest-ear module

$ tree eartest-ear/target/eartest-ear
eartest-ear/target/eartest-ear
|-- META-INF
|   `-- application.xml
|-- eartest-ejb-impl-1.0-SNAPSHOT.jar
|-- eartest-war-1.0-SNAPSHOT.war
`-- lib
    `-- eartest-ejb-api-1.0-SNAPSHOT.jar

2 directories, 4 files

Structure of eartest-war module

$ tree eartest-war/target/eartest-war
eartest-war/target/eartest-war
|-- META-INF
`-- WEB-INF
    `-- classes
        `-- eartest
            `-- war
                `-- MyServlet.class

5 directories, 1 file

MyServlet can reference eartest-ejb-api-1.0-SNAPSHOT.jar because it’s placed under lib directory in the parent EAR. this packaging style is called as Skinny WAR.

Structure of eartest-ejb-api

$ tree eartest-ejb-api/target/classes
eartest-ejb-api/target/classes
`-- eartest
    `-- ejb
        `-- api
            `-- Hello.class

3 directories, 1 file

Structure of eartest-ejb-impl

$ tree eartest-ejb-impl/target/classes
eartest-ejb-impl/target/classes
|-- META-INF
|   `-- ejb-jar.xml
`-- eartest
    `-- ejb
        `-- impl
            `-- HelloImpl.class

4 directories, 2 files

A problem with IntelliJ IDEA

IntelliJ has an annoying issue: Maven support cannot handle skinny wars for EAR deployments : IDEA-97324. this brings unnecessary eartest-ejb-api into WEB-INF/lib inside the WAR and brings following exception. to avoid this, I need to put <scope>provided</scope> in dependency declaration for eartest-ejb-api in pom.xml of eartest-war.

Caused by: java.lang.IllegalStateException: JBAS011048: Failed to construct component instance
	at org.jboss.as.ee.component.BasicComponent.constructComponentInstance(BasicComponent.java:162)
	at org.jboss.as.ee.component.BasicComponent.constructComponentInstance(BasicComponent.java:133)
	at org.jboss.as.ee.component.BasicComponent.createInstance(BasicComponent.java:89)
	at org.jboss.as.ee.component.ComponentRegistry$ComponentManagedReferenceFactory.getReference(ComponentRegistry.java:149)
	at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$5.createInstance(UndertowDeploymentInfoService.java:1233)
	at io.undertow.servlet.core.ManagedServlet$DefaultInstanceStrategy.start(ManagedServlet.java:215) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
	... 27 more
Caused by: java.lang.IllegalArgumentException: Can not set eartest.ejb.api.Hello field eartest.war.MyServlet.hello to eartest.ejb.api.Hello$$$view17
	at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167) [rt.jar:1.8.0_20]
	at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171) [rt.jar:1.8.0_20]
	at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81) [rt.jar:1.8.0_20]
	at java.lang.reflect.Field.set(Field.java:758) [rt.jar:1.8.0_20]
	at org.jboss.as.ee.component.ManagedReferenceFieldInjectionInterceptorFactory$ManagedReferenceFieldInjectionInterceptor.processInvocation(ManagedReferenceFieldInjectionInterceptorFactory.java:108)
	at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)
	at org.jboss.invocation.WeavedInterceptor.processInvocation(WeavedInterceptor.java:53)
	at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)
	at org.jboss.as.ee.component.AroundConstructInterceptorFactory$1.processInvocation(AroundConstructInterceptorFactory.java:28)
	at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)
	at org.jboss.as.ee.concurrent.ConcurrentContextInterceptor.processInvocation(ConcurrentContextInterceptor.java:45) [wildfly-ee-8.2.0.Final.jar:8.2.0.Final]
	at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)
	at org.jboss.invocation.ContextClassLoaderInterceptor.processInvocation(ContextClassLoaderInterceptor.java:64)
	at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)
	at org.jboss.invocation.InterceptorContext.run(InterceptorContext.java:326)
	at org.jboss.invocation.PrivilegedWithCombinerInterceptor.processInvocation(PrivilegedWithCombinerInterceptor.java:80)
	at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)
	at org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:61)
	at org.jboss.as.ee.component.BasicComponent.constructComponentInstance(BasicComponent.java:160)
	... 32 more


Doesn't InitialContext.doLookup() bring resource leak?


Posted on Thursday Feb 12, 2015 at 12:00PM in Technology


There’s a convenient static method called InitialContext.doLookup() which introduced at Java6. it uses Generics so we don’t need to cast returned object by hand. implementation is very simple as follows:

public static <T> T doLookup(String name) throws NamingException {
    return (T) (new InitialContext()).lookup(name);
}

I think it’s bad because there’s no way to invoke InitialContext#close() because doLookup() doesn’t save the reference to InitialContext instance anywhere. if it acquired some resource such as TCP socket it may brings resource leak.

Personally I will avoid use of doLookup() because of this reason while there are many opinion that it doesn’t need to close explicitly at most of environments. I guess I’m too sensitive about it but I have a history of strugging with leak of JDBC resources (Connection, Statement and ResultSet) so I’m very curious about this kind of problem.

Sometimes handling of InitialContext is annoying because it should be keep opened during use of returned instance on some environments or implementations. also I wonder why InitialContext doesn’t implemented AutoCloseable while it’s a perfect candidate for it.

For Servlets you could write as follows:

public class TestServlet extends HttpServlet {

    private Context context;
    private DataSource dataSource;

    @Override
    public void init() throws ServletException {
        try {
            context = new InitialContext();
            dataSource = (DataSource) context.lookup("java:comp/env/jdbc/derby");
        } catch (NamingException e) {
            throw new ServletException(e);
        }
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        try (Connection cn = dataSource.getConnection()) {
        	// database operations
        } catch (SQLException e) {
            throw new ServletException(e);
        }
    }

    @Override
    public void destroy() {
        if (context != null) {
            try {
                context.close();
            } catch (NamingException e) {
                // no-op
            }
        }
    }
}

In jberetweb, I wrote an interface named JobOperatorWork and a method intended to use with it called doWorkWithJobOperator() for ease of handling of InitialContext closing.

In Java EE environment, you could simply use @Resource or @EJB for avoiding annoying procedure of closing.


「わかりやすいJava EEウェブシステム入門」書評


Posted on Tuesday Dec 30, 2014 at 11:13PM in Technology


貴重な日本語のJava EE7入門書「わかりやすいJava EEウェブシステム入門」の書評.

Read More