I am developing a Java EE application that uses JAX-RS for the WebLayer.
I tried to break down the problem. So the code you'll see is just a cutout. For now everything works fine. As you can see I have an UserEndpoint
where a client can create a new user. After everything is done a verification mail is sent by the VerificationService
.
UserEndpoint
@Path("/users")
@Stateless
public class UserEndpoint {
@Inject
@AuthenticatedUser
private User authenticatedUser;
@EJB
private UserDAO userDAO;
@EJB
private TokenDAO tokenDAO;
@Inject
private PasswordValidator passwordValidator;
@Inject
private UserValidator validator;
@Inject
private VerificationService verificationService;
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public User createUser(User user) {
// Validation and Creation
// Verification
this.verificationService.sendVerificationMail(user);
return user;
}
}
VerificationService
@Singleton
public class VerificationService {
@Inject
private MailService mailSender;
@Inject
private TemplateService templateService;
public void sendVerificationMail(User user) {
this.templateService.setUserTemplate(TemplateCategory.VerificationTemplate, user);
mailSender.sendMail(new Message(
MessageDAO.systemEmailAddresses.get(0),
user.getEmail(),
templateService.getSubject(),
templateService.getContent()));
}
}
Because I want to have a scalable project I decided to encapsulate parts of the endpoint, so I can make use of it in other projects. Since every user has to be verified in one way or another I thought that the encapsulation of the verification process would be a good idea. The problem is that I have no clue how to realize that. My first approach was as followed:
CoreUserEndpoint
@Path("/users")
@Stateless
public abstract class CoreUserEndpoint<D extends BaseUserDAO<T>, T extends BaseUser, V extends CoreUserValidator<D, T>> extends EntityEndpoint<D, T, V> {
@EJB
private TokenDAO tokenDAO;
@Inject
private PasswordValidator passwordValidator;
@Inject
private VerificationService<T> verificationService;
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public User createUser(User user) {
// Validation and Creation
// Verification
this.verificationService.sendVerificationMail(user);
return user;
}
}
EntityEndpoint
@Stateless
public class EntityEndpoint<D extends CoreDAO<T>, T extends CoreEntity, V extends CoreValidator> {
protected D entityDAO;
@Inject
@AuthenticatedUser
protected T authenticatedUser;
protected V entityValidator;
}
VerificationService
@Singleton
public class VerificationService<T extends BaseUser> {
@Inject
private MailService mailSender;
@Inject
private TemplateService<T> templateService;
public void sendVerificationMail(User user) {
this.templateService.setUserTemplate(TemplateCategory.VerificationTemplate, user);
mailSender.sendMail(new Message(
MessageDAO.systemEmailAddresses.get(0),
user.getEmail(),
templateService.getSubject(),
templateService.getContent()));
}
}
When I tried this I get the famous WELD-001408: Unsatisfied dependencies
error. And I think I do understand why this is happening. As I read here I cannot make use of generics, neither for @Inject
nor for @EJB
. But if I am not able to use generics how can I encapsulate the core of my project? Is their any work around or a different approach? I am sure there already is a solution for that anywhere in the internet. But after 3 days of searching without making any progress I get really frustrated and thought It would be best to ask you guys. So I would really appreciate if you could point me in the right direction.
I'm just trying to understand the logic. Since my comments with questions are too long, I decided to post here in aswer section.
Disclaimer: It doesn't answer you question directly
So, let's start:
A generic class is defined with the following format:
class name<T1, T2, ..., Tn> { /* ... */ }
The type parameter section, delimited by angle brackets (<>), follows the class name. It specifies the type parameters (also called type variables)T1, T2, ..., and Tn
.
1. So by doing this:
public abstract class CoreUserEndpoint<D extends BaseUserDAO<T>, T extends BaseUser, V extends CoreUserValidator<D, T>>
the type variables D extends BaseUserDAO<T>, T extends BaseUser, V extends CoreUserValidator<D, T>
, instruct Java compiler that in order to use CoreUserEndpoint
one needs to specify the types.
2. Next when you do this:
public abstract class CoreUserEndpoint<...> extends EntityEndpoint<D, T, V>
you use the previously defined type arguments to be used in EntityEndpoint
. Now, compiler would look for classes (or interfaces, ...) named D
, T
and V
.
Here comes the part which I am not sure about. If compiler finds them from your declaration for CoreUserEndpoint
, then you're trying to force the class to extend from multiple classes, which is not allowed, by doing this:
public class EntityEndpoint<D extends CoreDAO<T>, T extends CoreEntity, V extends CoreValidator>
PS I would higly appreciate any feedback, if what I've written here makes any sence, from experience Java devs.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.