9.01.2015

EJB remote & Wildfly



До этого все примеры, которые мы рассматривали,  были локальными EJB бинами, которые запускались на одной виртуальной  java  машине (jvm),  и из под сервера wildfly.  Часто так бывает, что клиентский код находиться на другом компьютере и нам нужно  порой работать с ejb  бинами удаленно, т. е. вызвать методы ejb удаленно и получить результат. Что бы позволить такую роскошь, мы должны описать интерфейс с аннотаций @Remote и реализовать его в нашем ejb бине.  Давайте посмотрим на код интерфейса:

package com.vit.fly.ejb;

import javax.ejb.Remote;
import java.util.concurrent.Future;

@Remote
public interface Calculator {
    Future<Integer> add(int x, int y);
    void longRun(int x, int y);
}

Он описывает два метода, первый метод будет складывать 2 целых числа и возвращать нам сумму, второй будет выполнять “долгую” по времени операцию.  Опишем сам ejb  и реализуем интерфейс Calculator:

package com.vit.fly.remoteejb;

import org.jboss.logging.Logger;
import javax.annotation.Resource;
import javax.ejb.AsyncResult;
import javax.ejb.Asynchronous;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

@Stateless(name = "calculator")
public class CalculatorBean implements Calculator {
    private static Logger log = Logger.getLogger(CalculatorBean.class.getName());

    @Resource
    private SessionContext context;

    @Override
    @Asynchronous
    public Future<Integer> add(int x, int y) {
        try {
            TimeUnit.SECONDS.sleep(1L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return new AsyncResult<Integer>(x + y); //складываем 2 числа
    }



    @Override
    //@Asynchronous
    public void longRun(int x, int y) {
        try {
            TimeUnit.SECONDS.sleep(10L);//имитируем долгую работу, приостанавливаем поток на 10 секунд
           log.info("longRun method complete!");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Собираем все в jar файл и помещаем его в каталог JBOSS_HOME/Standalone/deployments, после деплоя,  в логах сервера wildfly  появятся строчки примерно такого вида:

2015-08-27 21:41:36,160 INFO  [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-2) JNDI bindings for session bean named calculator in deployment unit deployment "ejb-remote-example-server.jar" are as follows:

                java:global/ejb-remote-example-server/calculator!com.vit.fly.remoteejb.Calculator
                java:app/ejb-remote-example-server/calculator!com.vit.fly.remoteejb.Calculator
                java:module/calculator!com.vit.fly.remoteejb.Calculator
                java:jboss/exported/ejb-remote-example-server/calculator!com.vit.fly.remoteejb.Calculator
                java:global/ejb-remote-example-server/calculator
                java:app/ejb-remote-example-server/calculator
                java:module/calculator

2015-08-27 21:41:36,236 INFO  [org.jboss.weld.deployer] (MSC service thread 1-4) JBAS016005: Starting Services for CDI deployment: ejb-remote-example-server.jar

Перейдем к написанию клиента, который будет вызывать наш ejb  бин удаленно:

package com.vit.fly;

import com.vit.fly.remoteejb.Calculator;
import com.vit.fly.remoteejb.CalculatorBean;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.util.Properties;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

public class Main {

    private static Context context = null;

    public static void main(String[] args) throws Exception {

        try {
            Properties prop = new Properties();            prop.put(Context.INITIAL_CONTEXT_FACTORY,"org.jboss.naming.remote.client.InitialContextFactory");
            prop.put(Context.PROVIDER_URL, "http-remoting://127.0.0.1:8080");
            context = new InitialContext(prop);
            Calculator calculator = (Calculator) context.lookup("/ejb-remote-example-server/calculator!com.vit.fly.remoteejb.Calculator");
            System.out.println(calculator);
            Future<Integer> result = calculator.add(1, 4);
                        calculator.longRun(1, 2);
                       System.out.println(result.get(2, TimeUnit.SECONDS));              
        } finally {
            context.close();
        }
    }

}

Вам понадобится еще файл с настройками jboss-ejb-client.properties, положите его в classpath:

endpoint.name=client-endpoint
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
remote.connections=default
remote.connection.default.username=my-username-here
remote.connection.default.password=my-password-here
remote.connection.default.host=localhost
remote.connection.default.port=8080
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false

Запустим на выполнение наш пример, и получим результат работы метода:

авг 28, 2015 7:59:38 PM org.jboss.ejb.client.remoting.RemotingConnectionEJBReceiver associate
INFO: EJBCLIENT000013: Successful version handshake completed for receiver context EJBReceiverContext{clientContext=org.jboss.ejb.client.EJBClientContext@9df6e3, receiver=Remoting connection EJB receiver [connection=org.jboss.ejb.client.remoting.ConnectionPool$PooledConnection@bbe4b0,channel=jboss.ejb,nodename=kamaz1-pc]} on channel Channel ID b371683b (outbound) of Remoting connection 00eebce6 to localhost/127.0.0.1:8080
5

Как вы можете заметить, нам пришлось ждать результата окончания работы программы 11 секунд. Метод  longRun  отработал с задержкой в 10 секунд,  если вы сделаете  его асинхронным, вам будет не нужно ждать, пока метод завершит свою работу, то задержка у основной программы будет приблизительно около 1 секунды. И после запуска из программы метода, 10 секунд  метод  longRun  будет автономно работать вне зависимости от нашей основной программы, автономно.  Для этого нужно, просто раскоментировать аннотацию @Asynchronous у метода longRun и он станет асинхронным. Здесь я вам показываю работу еще одного  асинхронного  метода add, который возвращает результат посредством интерфейса Future.  У этого интерфейса есть метод  .get(2, TimeUnit.SECONDS) который принимает два параметра время, в течение которого ожидается результат, и в чем первый параметр измеряется, в моем случае в секундах. И на последок клиентской программе нужна библиотека jboss-client.jar, которая находиться в дистрибутиве wildfly, вообще-то  не хватающие библиотеки я устанавливаю из установленного мной дистрибутива. Просто организовываю поиск  нужного мне класса, нахожу библиотеку jar инсталирую её в .m2 репозитарий и подсовываю её maveny как зависимость. Вот мои pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.vit.fly.remoteejb</groupId>
    <artifactId>jboss_ejb1</artifactId>
    <version>1.0</version>
    <name>ejb remote server</name>
    <packaging>ejb</packaging>

    <repositories>
        <repository>
            <id>jboss-public-repository-group</id>
            <name>JBoss Public Maven Repository Group</name>
            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
            <layout>default</layout>
            <releases>
                <enabled>true</enabled>
                <updatePolicy>never</updatePolicy>
            </releases>
            <snapshots>
                <enabled>true</enabled>
                <updatePolicy>never</updatePolicy>
            </snapshots>
        </repository>
    </repositories>

    <dependencies>
       <dependency>
            <groupId>org.jboss.spec.javax.ejb</groupId>
            <artifactId>jboss-ejb-api_3.2_spec</artifactId>
            <version>1.0.0.Final</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.glassfish</groupId>
            <artifactId>javax.annotation</artifactId>
            <version>3.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>4.1.9.Final</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>4.1.9.Final</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>6.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>jboss-annotations-api_1.2_spec</artifactId>
            <version>1.0.0.Final</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.3</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.1</version>
                    <configuration>
                        <source>1.7</source>
                        <target>1.7</target>
                    </configuration>
                </plugin>
                <plugin>
                    <artifactId>maven-ejb-plugin</artifactId>
                    <version>2.4</version>
                    <configuration>
                        <ejbVersion>3.2</ejbVersion>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
        <finalName>ejb-remote-example-server</finalName>
    </build>
</project>

Комментариев нет:

Отправить комментарий