我有一个申请。每个用户对应于实体“客户”。在会话期间,用户使用其实体。
我有JAX-RS + EJB应用程序。我希望此实体作为单个实例可见并在所有服务中使用。我想使用CDI实现它。
首先,用户登录到应用程序。登录后,我想从基础中获取其实体并将其分配给单例,但是我没有成功。我尝试了@Singleton
注释(javax.inject
),@SessionScoped
和@ApplicationScoped
。
我该怎么办?
//Entity
@Entity
@SessionScope //or @Singlton/@ApplicationScope
class Client { fields }
//login service
@Inject
Client client;
//After login I want to assign an entity from db[cleintEntity]
//to entity which is available everywhere[client]
client = clientEntity;
我想这样做:
//some ejb
@Inject
Client client;
//use entity
我不想在整个应用程序中传输到实例的链接,但是我希望使用CDI在任何地方都可以使用它。
还是我需要创建一个单独的ClientDAO
,它将是我的单身汉?
答案 0 :(得分:1)
根据您的评论,您必须使用@SessionScope
。如果您想为所有用户提供一个实例,可以使用@Singleton
和@ApplicationScope
。
要解决您的问题,
您要在用户登录时实例化Client
。因此,当您使用登录服务时,该对象尚未实例化,因此您无法将其@Inject
实例化到您的登录服务,您应该记得删除@Inject
注释。
您需要使用@Produces
批注。当您希望控制类的实例化方式时,可以使用此注释。当CDI容器想要找到Client
类的实现时,如果它找到返回Client
并具有@Produces
批注的方法,则它会调用该方法,而不仅仅是实例化{{1 }}本身。您应该进行登录业务,然后创建Client
的实例并将其作为成员变量存储在登录服务中。然后在此类中添加一个返回该客户端对象的方法,并用Client
对该方法进行注释。您的登录服务的最终结构将如下所示:
@Produces
您还可以将 @SessionScope
public class LoginService {
private Client client;
public void login(String username, String password) {
// implement login business
// if login is successful
client = clientEntity;
}
@Produces
@SessionScope
public Client clientProducer() {
return this.client;
}
}
批注放在字段顶部。在这种情况下,CDI容器将使用存储在该字段上的值,而不是调用方法。
@Produces
当然,这应该被视为一种伪代码。我不知道您的业务的所有详细信息。也许您实现逻辑的方式是完全错误的;)。但是要解决此特定问题, @SessionScope
public class LoginService {
@Produces
@SessionScope
private Client client;
public void login(String username, String password) {
// implement login business
// if login is successful
client = clientEntity;
}
}
应该可以工作。