在具有 RPC 调度的 GWTP 项目中使用 EJB
Using EJBs in a GWTP project with RPC Dispatch
我们在 web/enterprise 应用程序中使用 GWTP RPC Dispatch 和 Guice。我们希望使用 EJB 将我们的业务逻辑放在我们的 EAR 的单独模块中。由于 RPC Dispatch 在这里起作用,所以只有一个 servlet,它有点被封装了。所以没有直接的方法来注入我们的 EJB,至少在不失去 EJB 的容器管理的情况下是这样。
是否有其他方法可以将 EJB 集成到我们的应用程序中?或者我在这里遗漏了什么?
所以经过一些研究,我似乎有两种方法可以在 Guice/RPC Dispatch 应用程序中使用 EJB 注入:
1。集中注入
EJB 注入在 GuiceServletContextListener
或您的 child class 的任何名称中工作。在那里你可以通过 @EJB
注释注入一个 bean,然后将引用传递给 getInjector()
方法中的模块:
import javax.ejb.EJB;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.servlet.GuiceServletContextListener;
public class GuiceServletConfig extends GuiceServletContextListener {
@EJB
private SampleBeanLocal sampleBean;
@Override
protected Injector getInjector() {
return Guice.createInjector(new ServerModule(), new BeanModule(sampleBean));
}
}
2。自定义注释
另一种方法是创建一个自定义注释,然后使用它在不可能的地方注入 bean。 here.
描述了实现
由于代码示例中存在一些缺陷,我也将post我的解决方案放在这里:
注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ TYPE, METHOD, FIELD})
public @interface GuiceEJB {
/**
* Name of the bean.
*
* @return Name of the bean.
*/
String name();
/**
* Local EJB as default type.
*
* @return bean type.
*/
String type() default "local";
}
TypeListener
import java.lang.reflect.Field;
import com.google.inject.TypeLiteral;
import com.google.inject.spi.TypeEncounter;
import com.google.inject.spi.TypeListener;
/**
* Custom Guice {@link TypeListener} for the {@link GuiceEJB} annotation.
*/
public class GuiceEJBTypeListener implements TypeListener {
@Override
public <I> void hear(TypeLiteral<I> typeLiteral, TypeEncounter<I> encounter) {
Class< ? > clazz = typeLiteral.getRawType();
while (clazz != null) {
// iterate through the fields of the class
for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(GuiceEJB.class)) {
encounter.register(new GuiceEJBMemberInjector<I>(field));
}
}
// repeat for super class
clazz = clazz.getSuperclass();
}
}
}
MembersInjector
import java.lang.reflect.Field;
import javax.naming.Context;
import javax.naming.InitialContext;
import com.google.inject.MembersInjector;
/**
* Custom member injector for {@link GuiceEJB} annotations.
*/
public class GuiceEJBMemberInjector<T> implements MembersInjector<T> {
/**
* Field that needs injection.
*/
private Field field;
/**
* Bean type.
*/
private String type;
/**
* Bean name.
*/
private String name;
/**
* @param field
*/
public GuiceEJBMemberInjector(Field field) {
this.field = field;
GuiceEJB annotation = field.getAnnotation(GuiceEJB.class);
this.type = annotation.type();
this.name = annotation.name();
this.field.setAccessible(true);
}
@Override
public void injectMembers(T t) {
try {
if ("local".compareToIgnoreCase(this.type) == 0) {
this.field.set(t, findLocalEJB());
}
} catch (Exception e) {
throw new GuiceEJBInjectException(e);
}
}
/**
* Lookup an local EJB for the given field.
*
* @return
*/
private Object findLocalEJB() {
Context initialContext = null;
Object localRef = null;
try {
// look up the bean by name
localRef = InitialContext.doLookup(this.name);
} catch (Exception e) {
throw new GuiceEJBInjectException(e);
} finally {
try {
if (initialContext != null)
initialContext.close();
} catch (Exception e) {
}
}
return localRef;
}
}
我们在 web/enterprise 应用程序中使用 GWTP RPC Dispatch 和 Guice。我们希望使用 EJB 将我们的业务逻辑放在我们的 EAR 的单独模块中。由于 RPC Dispatch 在这里起作用,所以只有一个 servlet,它有点被封装了。所以没有直接的方法来注入我们的 EJB,至少在不失去 EJB 的容器管理的情况下是这样。
是否有其他方法可以将 EJB 集成到我们的应用程序中?或者我在这里遗漏了什么?
所以经过一些研究,我似乎有两种方法可以在 Guice/RPC Dispatch 应用程序中使用 EJB 注入:
1。集中注入
EJB 注入在 GuiceServletContextListener
或您的 child class 的任何名称中工作。在那里你可以通过 @EJB
注释注入一个 bean,然后将引用传递给 getInjector()
方法中的模块:
import javax.ejb.EJB;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.servlet.GuiceServletContextListener;
public class GuiceServletConfig extends GuiceServletContextListener {
@EJB
private SampleBeanLocal sampleBean;
@Override
protected Injector getInjector() {
return Guice.createInjector(new ServerModule(), new BeanModule(sampleBean));
}
}
2。自定义注释
另一种方法是创建一个自定义注释,然后使用它在不可能的地方注入 bean。 here.
描述了实现由于代码示例中存在一些缺陷,我也将post我的解决方案放在这里:
注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ TYPE, METHOD, FIELD})
public @interface GuiceEJB {
/**
* Name of the bean.
*
* @return Name of the bean.
*/
String name();
/**
* Local EJB as default type.
*
* @return bean type.
*/
String type() default "local";
}
TypeListener
import java.lang.reflect.Field;
import com.google.inject.TypeLiteral;
import com.google.inject.spi.TypeEncounter;
import com.google.inject.spi.TypeListener;
/**
* Custom Guice {@link TypeListener} for the {@link GuiceEJB} annotation.
*/
public class GuiceEJBTypeListener implements TypeListener {
@Override
public <I> void hear(TypeLiteral<I> typeLiteral, TypeEncounter<I> encounter) {
Class< ? > clazz = typeLiteral.getRawType();
while (clazz != null) {
// iterate through the fields of the class
for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(GuiceEJB.class)) {
encounter.register(new GuiceEJBMemberInjector<I>(field));
}
}
// repeat for super class
clazz = clazz.getSuperclass();
}
}
}
MembersInjector
import java.lang.reflect.Field;
import javax.naming.Context;
import javax.naming.InitialContext;
import com.google.inject.MembersInjector;
/**
* Custom member injector for {@link GuiceEJB} annotations.
*/
public class GuiceEJBMemberInjector<T> implements MembersInjector<T> {
/**
* Field that needs injection.
*/
private Field field;
/**
* Bean type.
*/
private String type;
/**
* Bean name.
*/
private String name;
/**
* @param field
*/
public GuiceEJBMemberInjector(Field field) {
this.field = field;
GuiceEJB annotation = field.getAnnotation(GuiceEJB.class);
this.type = annotation.type();
this.name = annotation.name();
this.field.setAccessible(true);
}
@Override
public void injectMembers(T t) {
try {
if ("local".compareToIgnoreCase(this.type) == 0) {
this.field.set(t, findLocalEJB());
}
} catch (Exception e) {
throw new GuiceEJBInjectException(e);
}
}
/**
* Lookup an local EJB for the given field.
*
* @return
*/
private Object findLocalEJB() {
Context initialContext = null;
Object localRef = null;
try {
// look up the bean by name
localRef = InitialContext.doLookup(this.name);
} catch (Exception e) {
throw new GuiceEJBInjectException(e);
} finally {
try {
if (initialContext != null)
initialContext.close();
} catch (Exception e) {
}
}
return localRef;
}
}