Ръководство за настройка на EJB

1. Общ преглед

В тази статия ще обсъдим как да започнем с разработката на Enterprise JavaBean (EJB).

Enterprise JavaBeans се използват за разработване на мащабируеми, разпределени компоненти от страна на сървъра и обикновено капсулират бизнес логиката на приложението.

Ще използваме WildFly 10.1.0 като предпочитано сървърно решение, но можете да използвате всеки сървър за приложения на Java Enterprise по ваш избор.

2. Настройка

Нека да започнем, като обсъдим зависимостите на Maven, необходими за разработката на EJB 3.2, и как да конфигурираме сървъра за приложения WildFly, използвайки или приставката Maven Cargo, или ръчно.

2.1. Зависимост на Maven

За да използвате EJB 3.2 , не забравяйте да добавите най-новата версия към раздела за зависимости във вашия файл pom.xml :

 javax javaee-api 7.0 provided 
Ще намерите най-новата зависимост в хранилището на Maven. Тази зависимост гарантира, че всички API на Java EE 7 са налични по време на компилация. На предвидени обхват гарантира, че веднъж разгърнати, зависимостта ще бъдат предоставени от съда, където е внедрен.

2.2. Настройка на WildFly с Maven Cargo

Нека поговорим за това как да използваме приставката Maven Cargo за настройка на сървъра.

Ето кода за профила на Maven, който осигурява сървъра WildFly:

 wildfly-standalone    org.codehaus.cargo cargo-maven2-plugin ${cargo-maven2-plugin.version   wildfly10x   //download.jboss.org/ wildfly/10.1.0.Final/ wildfly-10.1.0.Final.zip      127.0.0.0  9990   testUser:admin1234!         

Използваме приставката за изтегляне на zip WildFly 10.1 директно от уебсайта на WildFly. Което след това се конфигурира, като се уверите, че името на хоста е 127.0.0.1 и зададете порта на 9990.

След това създаваме тестов потребител, като използваме свойството cargo.servlet.users , с потребителския идентификатор testUser и паролата admin1234 !.

След като конфигурацията на приставката приключи, трябва да можем да извикаме цел на Maven и да изтеглим, инсталираме, стартираме и разгърнем приложението на сървъра.

За да направите това, отидете до директорията ejb-remote и изпълнете следната команда:

mvn clean package cargo:run

Когато стартирате тази команда за първи път, тя ще изтегли zip файла WildFly 10.1, ще го извлече и ще изпълни инсталацията и след това ще го стартира. Той също така ще добави тестовия потребител, обсъден по-горе. Всяко по-нататъшно изпълнение няма да изтегли zip файла отново.

2.3. Ръчна настройка на WildFly

За да настроите WildFly ръчно, трябва сами да изтеглите инсталационния zip файл от уебсайта wildfly.org. Следващите стъпки са изглед на високо ниво на процеса на настройка на сървъра WildFly:

След като изтеглите и разархивирате съдържанието на файла на мястото, където искате да инсталирате сървъра, конфигурирайте следните променливи на средата:

JBOSS_HOME=/Users/$USER/../wildfly.x.x.Final JAVA_HOME=`/usr/libexec/java_home -v 1.8`

След това в директорията bin стартирайте ./standalone.sh за Linux базирани операционни системи или ./standalone.bat за Windows.

След това ще трябва да добавите потребител. Този потребител ще се използва за свързване към отдалечения EJB боб. За да разберете как да добавите потребител, трябва да разгледате документацията „добавяне на потребител“.

За подробни инструкции за настройка, моля, посетете документацията за Първи стъпки на WildFly.

Проектът POM е конфигуриран да работи с приставката Cargo и ръчната конфигурация на сървъра чрез задаване на два профила. По подразбиране е избран приставката Cargo. За да разположите приложението на вече инсталиран, конфигуриран и работещ сървър на Wildfly, изпълнете следната команда в директорията ejb-remote :

mvn clean install wildfly:deploy -Pwildfly-runtime

3. Дистанционно срещу локално

Бизнес интерфейсът за боб може да бъде локален или отдалечен.

A @Local annotated bean can only be accessed if it is in the same application as the bean that makes the invocation, i.e. if they reside in the same .ear or .war.

A @Remote annotated bean can be accessed from a different application, i.e. an application residing in a different JVM or application server.

There are some important points to keep in mind when designing a solution that includes EJBs:

  • The java.io.Serializable, java.io.Externalizable and interfaces defined by the javax.ejb package are always excluded when a bean is declared with @Local or @Remote
  • If a bean class is remote, then all implemented interfaces are to be remote
  • If a bean class contains no annotation or if the @Local annotation is specified, then all implemented interfaces are assumed to be local
  • Any interface that is explicitly defined for a bean which contains no interface must be declared as @Local
  • The EJB 3.2 release tends to provide more granularity for situations where local and remote interfaces need to explicitly defined

4. Creating the Remote EJB

Let's first create the bean's interface and call it HelloWorld:

@Remote public interface HelloWorld { String getHelloWorld(); }

Now we will implement the above interface and name the concrete implementation HelloWorldBean:

@Stateless(name = "HelloWorld") public class HelloWorldBean implements HelloWorld { @Resource private SessionContext context; @Override public String getHelloWorld() { return "Welcome to EJB Tutorial!"; } }

Note the @Stateless annotation on the class declaration. It denotes that this bean is a stateless session bean. This kind of bean does not have any associated client state, but it may preserve its instance state and is normally used to do independent operations.

The @Resource annotation injects the session context into the remote bean.

The SessionContext interface provides access to the runtime session context that the container provides for a session bean instance. The container then passes the SessionContext interface to an instance after the instance has been created. The session context remains associated with that instance for its lifetime.

The EJB container normally creates a pool of stateless bean's objects and uses these objects to process client requests. As a result of this pooling mechanism, instance variable values are not guaranteed to be maintained across lookup method calls.

5. Remote Setup

In this section, we will discuss how to setup Maven to build and run the application on the server.

Let's look at the plugins one by one.

5.1. The EJB Plugin

The EJB plugin which is given below is used to package an EJB module. We have specified the EJB version as 3.2.

The following plugin configuration is used to setup the target JAR for the bean:

 maven-ejb-plugin 2.4  3.2  

5.2. Deploy the Remote EJB

To deploy the bean in a WildFly server ensure that the server is up and running.

Then to execute the remote setup we will need to run the following Maven commands against the pom file in the ejb-remote project:

mvn clean install 

Then we should run:

mvn wildfly:deploy

Alternatively, we can deploy it manually as an admin user from the admin console of the application server.

6. Client Setup

After creating the remote bean we should test the deployed bean by creating a client.

First, let's discuss the Maven setup for the client project.

6.1. Client-Side Maven Setup

In order to launch the EJB3 client we need to add the following dependencies:

 org.wildfly wildfly-ejb-client-bom pom import 

We depend on the EJB remote business interfaces of this application to run the client. So we need to specify the EJB client JAR dependency. We add the following in the parent pom:

 com.baeldung.ejb ejb-remote ejb 

The is specified as ejb.

6.2. Accessing the Remote Bean

We need to create a file under src/main/resources and name it jboss-ejb-client.properties that will contain all the properties that are required to access the deployed bean:

remote.connections=default remote.connection.default.host=127.0.0.1 remote.connection.default.port=8080 remote.connection.default.connect.options.org.xnio.Options .SASL_POLICY_NOANONYMOUS = false remote.connection.default.connect.options.org.xnio.Options .SASL_POLICY_NOPLAINTEXT = false remote.connection.default.connect.options.org.xnio.Options .SASL_DISALLOWED_MECHANISMS = ${host.auth:JBOSS-LOCAL-USER} remote.connection.default.username=testUser remote.connection.default.password=admin1234! 

7. Creating the Client

The class that will access and use the remote HelloWorld bean has been created in EJBClient.java which is in the com.baeldung.ejb.client package.

7.1 Remote Bean URL

The remote bean is located via a URL that conforms to the following format:

ejb:${appName}/${moduleName}/${distinctName}/${beanName}!${viewClassName}
  • The ${appName} is the application name of the deployment. Here we have not used any EAR file but a simple JAR or WAR deployment, so the application name will be empty
  • The ${moduleName} is the name we set for our deployment earlier, so it is ejb-remote
  • The ${distinctName} is a specific name which can be optionally assigned to the deployments that are deployed on the server. If a deployment doesn't use distinct-name then we can use an empty String in the JNDI name, for the distinct-name, as we did in our example
  • The ${beanName} variable is the simple name of the implementation class of the EJB, so in our example it is HelloWorld
  • ${viewClassName} denotes the fully-qualified interface name of the remote interface

7.2 Look-up Logic

Next, let's have a look at our simple look-up logic:

public HelloWorld lookup() throws NamingException { String appName = ""; String moduleName = "remote"; String distinctName = ""; String beanName = "HelloWorld"; String viewClassName = HelloWorld.class.getName(); String toLookup = String.format("ejb:%s/%s/%s/%s!%s", appName, moduleName, distinctName, beanName, viewClassName); return (HelloWorld) context.lookup(toLookup); }

In order to connect to the bean we just created, we will need a URL which we can feed into the context.

7.3 The Initial Context

We'll now create/initialize the session context:

public void createInitialContext() throws NamingException { Properties prop = new Properties(); prop.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming"); prop.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFacto[ERROR] prop.put(Context.PROVIDER_URL, "http-remoting://127.0.0.1:8080"); prop.put(Context.SECURITY_PRINCIPAL, "testUser"); prop.put(Context.SECURITY_CREDENTIALS, "admin1234!"); prop.put("jboss.naming.client.ejb.context", false); context = new InitialContext(prop); }

To connect to the remote bean we need a JNDI context. The context factory is provided by the Maven artifact org.jboss:jboss-remote-naming and this creates a JNDI context, which will resolve the URL constructed in the lookup method, into proxies to the remote application server process.

7.4 Define Lookup Parameters

We define the factory class with the parameter Context.INITIAL_CONTEXT_FACTORY.

The Context.URL_PKG_PREFIXES is used to define a package to scan for additional naming context.

The parameter org.jboss.ejb.client.scoped.context = false tells the context to read the connection parameters (such as the connection host and port) from the provided map instead of from a classpath configuration file. This is especially helpful if we want to create a JAR bundle that should be able to connect to different hosts.

The parameter Context.PROVIDER_URL defines the connection schema and should start with http-remoting://.

8. Testing

To test the deployment and check the setup, we can run the following test to make sure everything works properly:

@Test public void testEJBClient() { EJBClient ejbClient = new EJBClient(); HelloWorldBean bean = new HelloWorldBean(); assertEquals(bean.getHelloWorld(), ejbClient.getEJBRemoteMessage()); }

With the test passing, we can now be sure everything is working as expected.

9. Conclusion

Така че ние създадохме EJB сървър и клиент, който извиква метод на отдалечен EJB. Проектът може да се изпълни на всеки сървър на приложения, като добави правилно зависимостите за този сървър.

Целият проект може да бъде намерен в GitHub.