我是EJB的新手。这是我第一次处理EJB。
我有两个完整的应用程序。第一个应用程序是部署在WildFly 8上的EJB bean,第二个是将使用服务器上的Bean的客户端应用程序。
服务器应用程序:
package com.apress.ejb.chapter02.business;
// Remote Interface
@Remote
public interface SearchFacade {
List<String> wineSearch(String wineType);
String wineSearchByCountry();
}
package com.apress.ejb.chapter02.business;
// Local Interface
@Local
public interface SearchFacadeLocal {
List<String> wineSearch(String wineType);
String wineSearchByCountry();
}
上述接口的服务器实现:
package com.apress.ejb.chapter02;
/**
* Session Bean implementation class SearchFacadeBean
*/
@Stateless(name="SearchFacade")
//@LocalBean
public class SearchFacadeBean implements SearchFacade, SearchFacadeLocal{
private Map<String, String> countryMap = new HashMap<String, String>();
/**
* Default constructor.
*/
public SearchFacadeBean() {
}
public List<String> wineSearch(String wineType) {
List<String> wineList = new ArrayList<String>();
if(wineType.equals("red")){
wineList.add("Bordeaux");
wineList.add("Merlot");
wineList.add("Pinot Noir");
}else if(wineType.equals("white")){
wineList.add("Chardonnay");
}
return wineList;
}
public String wineSearchByCountry() {
return null;
}
@PostConstruct
public void initializeCountryWineList(){
countryMap.put("Australia", "Sauvignon Blanc");
countryMap.put("Australia", "Grenache");
countryMap.put("France","Gewurztraminer");
countryMap.put("France","Bordeaux");
System.out.println("SearchFacadeBean just CREATED... and country wine list FILLED");
}
@PreDestroy
public void destroyWineList() {
countryMap.clear();
System.out.println("SearchFacadeBean is going to be DESTROYED... wine list is EMPTIED");
}
@AroundInvoke
public Object timerLog(InvocationContext ctx) throws Exception{
String beanClassName = ctx.getClass().getName();
String businessMethodName = ctx.getMethod().getName();
String target = beanClassName + "." + businessMethodName ;
long startTime = System.currentTimeMillis();
System.out.println("Invoking: " + target);
Object ob = null;
try{
ob = ctx.proceed();
}finally{
System.out.println ("Exiting" + target);
long totalTime = System.currentTimeMillis() - startTime;
System.out.println ("Business method" + businessMethodName +
"in" + beanClassName + "takes" + totalTime + "ms to execute");
}
return ob;
}
}
Server Maven POM:
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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>searchFacade</groupId>
<artifactId>SearchFacadeSessionBean</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>ejb</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- other plugin versions -->
<version.compiler.plugin>3.1</version.compiler.plugin>
<version.ejb.plugin>2.3</version.ejb.plugin>
<!-- maven-compiler-plugin -->
<maven.compiler.target>1.7</maven.compiler.target>
<maven.compiler.source>1.7</maven.compiler.source>
</properties>
<!-- Define the version of WildFly's Java EE 7 APIs we want to use -->
<!-- WildFly distributes a complete set of Java EE 7 APIs including a Bill
of Materials (BOM). A BOM specifies the versions of a "stack" (or a collection)
of artifacts. We use this here so that we always get the correct versions
of artifacts. Here we use the jboss-javaee-6.0 stack (you can read this as
the WildFly stack of the Java EE 7 APIs). You can actually use this stack with
any version of WildFly AS that implements Java EE 7, not just WildFly AS 7! -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.wildfly.bom</groupId>
<artifactId>jboss-javaee-7.0-with-all</artifactId>
<version>8.2.1.Final</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Import the Common Annotations API (JSR-250), we use provided scope
as the API is included in JBoss AS 7 -->
<dependency>
<groupId>org.jboss.spec.javax.annotation</groupId>
<artifactId>jboss-annotations-api_1.1_spec</artifactId>
<scope>provided</scope>
</dependency>
<!-- Import the EJB 3.1 API, we use provided scope as the API is included in JBoss AS 7 -->
<dependency>
<groupId>org.jboss.spec.javax.ejb</groupId>
<artifactId>jboss-ejb-api_3.1_spec</artifactId>
<version>1.0.0.Final</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.0-api</artifactId>
<version>1.0.1.Final</version>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Compiler plugin enforces Java 1.7 compatibility and activates annotation
processors -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${version.compiler.plugin}</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
<excludes>
<exclude>com/apress/ejb/chapter03/entities/*.java</exclude>
<exclude>com/apress/ejb/chapter03/services/*.java</exclude>
</excludes>
</configuration>
</plugin>
<!-- JBoss AS plugin to deploy the application -->
<plugin>
<groupId>org.wildfly.plugins</groupId>
<artifactId>wildfly-maven-plugin</artifactId>
<version>1.1.0.Final</version>
<configuration>
<filename>${project.build.finalName}.jar</filename>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ejb-plugin</artifactId>
<version>${version.ejb.plugin}</version>
<configuration>
<ejbVersion>3.1</ejbVersion>
<!-- this is false by default -->
<generateClient>true</generateClient>
</configuration>
</plugin>
</plugins>
</build>
</project>
当我部署到WildFly 8时,控制台中会显示以下两个绑定:
(1)
10:06:22,593 INFO [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-1) JNDI bindings for session bean named SearchFacade in deployment unit deployment "SearchFacadeSessionBean.jar" are as follows:
java:global/SearchFacadeSessionBean/SearchFacade!com.apress.ejb.chapter02.business.SearchFacade
java:app/SearchFacadeSessionBean/SearchFacade!com.apress.ejb.chapter02.business.SearchFacade
java:module/SearchFacade!com.apress.ejb.chapter02.business.SearchFacade
java:jboss/exported/SearchFacadeSessionBean/SearchFacade!com.apress.ejb.chapter02.business.SearchFacade
java:global/SearchFacadeSessionBean/SearchFacade!com.apress.ejb.chapter02.business.SearchFacadeLocal
java:app/SearchFacadeSessionBean/SearchFacade!com.apress.ejb.chapter02.business.SearchFacadeLocal
java:module/SearchFacade!com.apress.ejb.chapter02.business.SearchFacadeLocal
(2)
6:22,609 INFO [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-3) JNDI bindings for session bean named SearchFacade in deployment unit deployment "SearchFacadeSessionBean-0.0.1-SNAPSHOT.jar" are as follows:
java:global/SearchFacadeSessionBean-0.0.1-SNAPSHOT/SearchFacade!com.apress.ejb.chapter02.business.SearchFacade
java:app/SearchFacadeSessionBean-0.0.1-SNAPSHOT/SearchFacade!com.apress.ejb.chapter02.business.SearchFacade
java:module/SearchFacade!com.apress.ejb.chapter02.business.SearchFacade
java:jboss/exported/SearchFacadeSessionBean-0.0.1-SNAPSHOT/SearchFacade!com.apress.ejb.chapter02.business.SearchFacade
java:global/SearchFacadeSessionBean-0.0.1-SNAPSHOT/SearchFacade!com.apress.ejb.chapter02.business.SearchFacadeLocal
java:app/SearchFacadeSessionBean-0.0.1-SNAPSHOT/SearchFacade!com.apress.ejb.chapter02.business.SearchFacadeLocal
java:module/SearchFacade!com.apress.ejb.chapter02.business.SearchFacadeLocal
令我惊讶的是,我没有在任何绑定中看到实现类&#34; SearchFacadeBean&#34; 。它仅显示接口(SearchFacade,SearchFacadeLocal)。
客户申请:
//Client POM
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>sessionBeanClient</groupId>
<artifactId>SearchFacadeSessionBeanClient</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- JBoss dependency versions -->
<version.wildfly>8.1.0.Final</version.wildfly>
<version.jboss.spec.javaee.7.0>1.0.0.Final</version.jboss.spec.javaee.7.0>
<!-- other plugin versions -->
<version.compiler.plugin>3.1</version.compiler.plugin>
<version.ejb.plugin>2.3</version.ejb.plugin>
<!-- maven-compiler-plugin -->
<maven.compiler.target>1.7</maven.compiler.target>
<maven.compiler.source>1.7</maven.compiler.source>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.jboss.spec</groupId>
<artifactId>jboss-javaee-7.0</artifactId>
<version>${version.jboss.spec.javaee.7.0}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.wildfly</groupId>
<artifactId>wildfly-ejb-client-bom</artifactId>
<version>${version.wildfly}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Business Interfaces of the server EJB. -->
<dependency>
<groupId>searchFacade</groupId>
<artifactId>SearchFacadeSessionBean</artifactId>
<type>ejb</type>
<version>${project.version}</version>
</dependency>
<!-- Import the transaction spec API, we use runtime scope because we aren't
using any direct reference to the spec API in our client code -->
<dependency>
<groupId>org.jboss.spec.javax.transaction</groupId>
<artifactId>jboss-transaction-api_1.2_spec</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Import the EJB 3.1 API, we use runtime scope because we aren't using
any direct reference to EJB spec API in our client code -->
<dependency>
<groupId>org.jboss.spec.javax.ejb</groupId>
<artifactId>jboss-ejb-api_3.2_spec</artifactId>
<scope>runtime</scope>
</dependency>
<!-- JBoss EJB client API jar. We use runtime scope because the EJB client
API isn't directly used in this example. We just need it in our runtime classpath -->
<dependency>
<groupId>org.jboss</groupId>
<artifactId>jboss-ejb-client</artifactId>
<scope>runtime</scope>
</dependency>
<!-- client communications with the server use XNIO -->
<dependency>
<groupId>org.jboss.xnio</groupId>
<artifactId>xnio-api</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.jboss.xnio</groupId>
<artifactId>xnio-nio</artifactId>
<scope>runtime</scope>
</dependency>
<!-- The client needs JBoss remoting to access the server -->
<dependency>
<groupId>org.jboss.remoting</groupId>
<artifactId>jboss-remoting</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.jboss</groupId>
<artifactId>jboss-remote-naming</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Remote EJB accesses can be secured -->
<dependency>
<groupId>org.jboss.sasl</groupId>
<artifactId>jboss-sasl</artifactId>
<scope>runtime</scope>
</dependency>
<!-- data serialization for invoking remote EJBs -->
<dependency>
<groupId>org.jboss.marshalling</groupId>
<artifactId>jboss-marshalling-river</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Compiler plugin enforces Java 1.7 compatibility and activates annotation processors -->
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>${version.compiler.plugin}</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.5.0</version>
<!-- version>${version.exec.plugin}</version-->
<executions>
<execution>
<goals>
<!-- goal>exec</goal-->
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>java</executable>
<workingDirectory>${project.build.directory}/exec-working-directory</workingDirectory>
<mainClass>searchFacadeClient.Client</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
客户类:
package searchFacadeClient;
public class ClientUtility {
private static Context initialContext;
private static final String PKG_INTERFACES = "org.jboss.ejb.client.naming";
public static Context getInitialContext() {
if (initialContext == null) {
//Properties properties = new Properties();
Hashtable properties = new Hashtable();
properties.put(Context.URL_PKG_PREFIXES, PKG_INTERFACES);
try {
initialContext = new InitialContext(properties);
} catch (NamingException e) {
// TODO Auto-generated catch block
System.out.println("THERE IS A HUGE RPROBLEM..........");
e.printStackTrace();
}
}
return initialContext;
}
}
package searchFacadeClient;
public class Client {
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Enter wine Type(red/white): ");
//System.out.println("Enter 's' to EXIT: ");
String wineName = reader.readLine();
// Invoke a stateless bean
try {
List<String> wines = getWines(wineName);
for(String wine: wines){
System.out.println(wine);
}
} catch (NamingException e) {
System.out.println("Naming Exception: ");
e.printStackTrace();
}
}
private static List<String> getWines(String wineType)throws NamingException{
SearchFacade searchWines = doLookup();
return searchWines.wineSearch(wineType);
}
private static SearchFacade doLookup() {
Context context = null;
SearchFacade bean = null;
try {
// 1. Obtaining Context
context = ClientUtility.getInitialContext();
// 2. Generate JNDI Lookup name
String lookupName = getLookupName(); System.out.println("Lookup name: " + lookupName);
// 3. Lookup and cast
bean = (SearchFacade) context.lookup(lookupName);
} catch (NamingException e) {
e.printStackTrace();
}
return bean;
}
private static String getLookupName() {
/*
* The app name is the EAR name of the deployed EJB without .ear suffix.
* Since we haven't deployed the application as a .ear, the app name for
* us will be an empty string
*/
String appName = "";
/*
* The module name is the JAR name of the deployed EJB without the .jar
* suffix.
*/
String moduleName = "SearchFacadeSessionBean-0.0.1-SNAPSHOT";
/*
* AS7 allows each deployment to have an (optional) distinct name. This
* can be an empty string if distinct name is not specified.
*/
String distinctName = "";
// The EJB bean implementation class name
String beanName = "SearchFacadeBean";
// Fully qualified remote interface name
final String interfaceName = "com.apress.ejb.chapter02.business.SearchFacade";
// Create a look up string name
String name = "ejb:" + appName + "/" + moduleName + "/" + distinctName
+ "/" + beanName + "!" + interfaceName;
/*String name = "java:" + appName + "/" + moduleName + "/" + distinctName
+ "/" + beanName + "!" + interfaceName;*/
// return name;
return "ejb:SearchFacadeSessionBean/SearchFacade!com.apress.ejb.chapter02.business.SearchFacade";
}
}
如果您查看有关&#34; name&#34; 变量的最后几条陈述,其中一些陈述在评论中。当我返回&#34; name&#34; 变量中的值时,我得到: ejb:/SearchFacadeSessionBean-0.0.1-SNAPSHOT//SearchFacadeBean!com.apress.ejb。 chapter02.business.SearchFacade 我知道这是错的。
那里不应该有两个斜线,但我认为我已经给出了上述变量的所有正确值。所以我决定把这个&#34;名称&#34;在评论中变量并尝试从服务器控制台进行一些出价。因此,在运行客户端应用程序时,您在下面看到的结果(例外)部分是由于"getLookupName()"
函数返回字符串。
当我运行客户端应用程序来调用Beans时,我得到以下异常:输入wine类型(红色/白色):
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:294)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassCastException: org.jboss.ejb.client.naming.ejb.EjbNamingContext cannot be cast to com.apress.ejb.chapter02.business.SearchFacade
at searchFacadeClient.Client.doLookup(Client.java:47)
at searchFacadeClient.Client.getWines(Client.java:33)
at searchFacadeClient.Client.main(Client.java:22)
jboss.ejb.client.properties 文件是:
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
remote.connections=default
remote.connection.default.host=localhost
#remote.connection.default.port = 4447
remote.connection.default.port = 8080
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
我认为可能导致问题的领域是:
(1)服务器控制台日志中的绑定不会显示有关Bean实现类的任何信息。
(2)我认为实施类没有部署到服务器
(3)问题也可能来自SERVER和客户端POM,但不确切知道在哪里,可能会遗漏一些东西。
(4)另一个主要问题是我尝试使用MAVEN_WILDFLY_PLUGIN部署应用程序,但我在控制台中收到以下错误::
[ERROR] Failed to execute goal org.wildfly.plugins:wildfly-maven-plugin:1.1.0.Final:deploy (default-cli) on project SearchFacadeSessionBean: Failed to execute goal deploy. java.net.ConnectException: WFLYPRT0053: Could not connect to http-remoting://localhost:9990. The connection failed: Connection refused: no further information -> [Help 1]
所以我决定使用eClipse中的服务器控制台视图部署它,方法是右键单击WildFly并选择添加/删除。我不知道以这种方式部署它是否会导致问题。