如何使用Java EE 6将EJB注入域对象(JPA实体)?
我们正在开始一个基于EJB 3.0的新项目.我有一个"春天"的背景(并喜欢它),所以对我来说,松耦合和可测试性是必须具备的.这篇文章不应该是关于"ejb vs. spring".如果您已经拥有真正的项目经验,那将是完美的.
这是一些示例代码来演示问题:
客户端 - > ejb - >协作者1 - >协作者.. - >协作者n
<!-- language: java -->
@Stateless
public class SampleService {
// or @Inject via CDI
// or @Autowired via Spring
@EJB // or just use a stateless session bean via EJB 3.0
private Bank bank;
// same for this component
@EJB
private Calculator calc;
// both collaborators must be settable from outside, to make everything testable (and mockable)
/**
* sample "business service" called …Run Code Online (Sandbox Code Playgroud) 我刚刚开始使用Netbeans 7.1测试版,它正在调出我以前从未见过的类型的错误.特别:
A managed bean with a public field should not declare any scope other than @Dependent.
它抱怨的领域是public static final.我可以理解对非静态字段的限制,但我想不出一个很好的理由不允许静态字段.不幸的是我使用了很多,因为我不喜欢在我的代码中使用常量.
我注意到即使我在编辑器的边缘得到红点,maven驱动的构建仍然有效,GlassFish仍然以我期望的方式运行我的应用程序.
那么我对这个问题的看法是什么?我是否必须在其他地方移动我的静态字段,还是有其他方法来处理它?
JSR-299规范在§3.1中说明:
如果托管bean类是泛型类型,则它必须具有范围@Dependent.如果具有参数化bean类的托管bean声明除@Dependent之外的任何范围,则容器会自动检测问题并将其视为定义错误.
有效地意味着你不能这样做:
@Named
@SessionScoped or @RequestScoped or similar
public class MyProducer<T> {...}
Run Code Online (Sandbox Code Playgroud)
这个决定的技术原因是什么?
它是否会在即将发布的CDI版本中得到补救?
是否有处理/解决此问题的最佳做法?
谢谢
编辑 - 我经常使用的解决方法是将通用POJO-bean注入到具有所需范围的bean中.通常,但并非总是如此.
我们有一个webapp,目前正在使用Java EE 7,JSF 2.2和Glassfish 4.0开发.有两个特定的托管bean,它们具有循环依赖性.
UsuarioController
@Named
@SessionScoped
public class UsuarioController implements Serializable {
/** snipet **/
@Inject
private EnderecoController enderecoController;
/** snipet **/
}
Run Code Online (Sandbox Code Playgroud)
EnderecoController
@Named
@ViewScoped
public class EnderecoController {
/** snipet **/
@Inject
private UsuarioController esuarioController;
/** snipet **/
}
Run Code Online (Sandbox Code Playgroud)
当webapp打包并部署到普通的glassfish 4.0安装时,它可以正常工作.
但是,在开发过程中,我们使用maven-embedded-glassfish在IDE内部进行本地测试.应用程序部署失败,出现以下异常.
SEVERE: Exception while loading the app : CDI deployment failure:WELD-001408 Unsatisfied dependencies for type [EnderecoController] with qualifiers [@Default] at injection point [[BackedAnnotatedField] @Inject private net.jhm.exemplo.view.UsuarioController.enderecoController]
org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [EnderecoController] …Run Code Online (Sandbox Code Playgroud) 我有一个使用JSF 2.2(Mojorra 2.1.3)和CDI 1.1(Weld 2.0.3)在Servlet 3.0容器(Jetty 9.0.4)上运行的Web应用程序.没有使用完整的应用程序服务器.在这个应用程序中,我还有一个服务REST请求的JAX-RS 2.0(Jersey 2.2)资源类.我已经集成了JAXB绑定和JSON编组(Jackson 2.2).我使用Maven 3.0.5进行构建管理.这些是我项目设置的相关部分:
Maven pom.xml:
...
<dependencies>
<!-- Servlet 3.0 API -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- Contexts and Dependency Injection for Java EE -->
<dependency>
<groupId>org.jboss.weld.servlet</groupId>
<artifactId>weld-servlet</artifactId>
<version>2.0.3.Final</version>
</dependency>
<!-- JavaServer Faces -->
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>2.2.2</version>
</dependency>
<!-- JAX-RS RESTful Web Services -->
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.2</version>
</dependency>
<!-- JSON Mapping Framework -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.2</version>
</dependency> …Run Code Online (Sandbox Code Playgroud) 我有一个通用的抽象模板类.我想如果我创建特定于类型的生成器,我可以直接在泛型类中注入一些DAO服务.但我不能.
为什么?我怎么能解决这个问题呢?
abstract class MyView<T> {
@Inject
MyDao<T> dao;
//some more template methods that make use of the dao
void someMethod() {
dao.use();
}
}
class CustomerView extends MyView<Customer> {
//javax.enterprise.inject.AmbiguousResolutionException: Ambigious resolution
}
class DaoManager {
@Produces
MyDao<Customer> getDaoCustomer() {
return DaoFactory.make(Customer.class);
}
@Produces
MyDao<Product> getDaoProduct() {
return DaoFactory.make(Product.class);
}
}
Run Code Online (Sandbox Code Playgroud)
当我注射例如@Inject MyDao<Customer> dao;它它完美地工作.但不是泛型......
我很难理解@DependentCDI 1.0和CDI 1.1中作用域的有效生命周期.到目前为止,我的实验得出了以下结论:
@Dependent作用域的bean没有代理.@PreDestroy当@Dependentbean被销毁时,不会调用任何方法.Provider.get()总是创建一个@Dependentbean 的新实例.@Dependent由@ApplicationScopedbean的Provider<>字段创建的bean 被"泄露",因为它仍然"属于" Provider.@Dependent类似Providers 泄漏豆类的证据(还有!).(虽然这可能是因为这些特定的 @Dependent bean是由@Produces方法创建的......!)我看到CDI 1.1已添加了一种destroy()方法Instance<>,可能是为了解决CDI 1.0中的内存泄漏问题.但那怎么样Provider<>- CDI 1.1中是否还会泄漏?(如果确实如此,那么你应该怎么用Provider.get()?)
基本上,我有几个@ApplicationScopedbean/@SingletonEJB,我@Inject Provider试图Provider.get()用作两者的工厂@Dependent和@RequestScoped"帮助"bean.我绝对不希望这些bean"属于"他们的Provider字段,因为我需要将bean随后进行垃圾收集:
public void updateStuff() {
Helper helper = …Run Code Online (Sandbox Code Playgroud) 我有这个代码:
class Patient {
@Inject Syringe syringe;
@PostConstruct
void sayThankyouDoc() {
System.out.println("That hurt like crazy!");
}
}
@RunWith(MockitoJUnitRunner.class)
class TestCase {
@Mock
Syringe siringeMock;
@InjectMocks
Patient patient;
//...
}
Run Code Online (Sandbox Code Playgroud)
我希望Mockito能够调用PostConstruct,但我必须添加:
@Before
public void simulate_post_construct() throws Exception {
Method postConstruct = Patient.class.getDeclaredMethod("sayThankyouDoc", null);
postConstruct.setAccessible(true);
postConstruct.invoke(patient);
}
Run Code Online (Sandbox Code Playgroud)
有一个更好的方法吗?
我有一个关于bean.xml文件的正确格式和用法的问题.在我的项目中,我通常将此内容用于我的bean.xml文件(不使用explizit bean声明):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>
Run Code Online (Sandbox Code Playgroud)
这在WildFly 8和9中运行良好.但是我在GlassFish 4中有部署问题.在问题:Glassfish 4,CDI中的简单示例失败,WELD-001408不满意的依赖关系我写了另一种格式:
<beans
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
bean-discovery-mode="all">
</beans>
Run Code Online (Sandbox Code Playgroud)
使用了不同的命名空间.并且GlassFish4似乎关心这一点.
用于JEE7的空bean.xml文件的正确格式是什么?