Injecting generic Beans with CDI/Weld - java-ee-6

I just come from my tiny nice JavaSE/Guice world and am currently discovering the path of "carried by the container"-EE6. After having some trouble with Glassfish3.1, I just switched to JBoss and am now facing a problem that shouldnt be one.
As infrastructural assisting class, im trying to create a generic repository/DAO for any kind of entity. In a very simple manner, this might look like this one.
public class Repository<E, K extends Serializable & Comparable<K>> {
private final Instance<EntityManager> entityManagerInstance;
protected final Class<E> getDomainObjectClass() {
return domainObjectClass;
}
private final Class<E> domainObjectClass;
protected final EntityManager getEntityManager() {
return entityManagerInstance.get();
}
#Inject
public Repository(Instance<EntityManager> entityManageryProvider, Provider<E> domainObjectProvider) {
//This is a dirty hack, sadly :(
domainObjectClass = (Class<E>)domainObjectProvider.get().getClass();
this.entityManagerInstance = entityManageryProvider;
}
public final void persist(E domainObject) {
final EntityManager em = getEntityManager();
em.persist(domainObject);
}
public final Collection<E> getAllEntities() {
final EntityManager em = getEntityManager();
final CriteriaBuilder cb = em.getCriteriaBuilder();
final CriteriaQuery<E> query = cb.createQuery(getDomainObjectClass());
final List<E> result = em.createQuery(query).getResultList();
return Collections.unmodifiableList(result);
}
public final E find(K id) {
Preconditions.checkNotNull(id);
final EntityManager em = getEntityManager();
return em.find(getDomainObjectClass(), id);
}
// [...]
}
Now there may be a bean that does not require entity-dependent query capabilities but just a repository of a certain entity type, like (might be a test case):
public class DomainObjectARepositoryTest{
#Inject
Repository<DomainObjectA, PersistableUUID> domainObjectARepository;
#Test
public void testMitarbeitererstellung() {
for (DomainObjectA a : domainObjectARepository.getAllEntities()) {
// do cool stuff
}
}
}
Unfortunatly Weld does not seem to like this kind of generic injection. At deployment time, I get the following error:
state=Create: org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [Repository<DomainObjectA , PersistableUUID>] with qualifiers [#Default] at injection point [[field] #Inject sompackage.DomainObjectARepositoryTest.domainObjectARepository]
Am I missing something or did they just forgot to implement generic injects? As far as I understand the generic stuff, it is erasured after compiletime anyway - even this worked so fine in guice3 so far.
Kind regards,
avi
edit: found a comment by garvin king that this behavior is in the spec, but not implemented in weld, (staement was in june 2009)

That's rather a long comment than a complete answer to your question, but might point you in the right direction:
I'm following the discussions in seam-dev & weld-dev since quite some time, and do not remember that anything like this ever popped up. So my guess would be that it hasn't been on the agenda ever since Gavin commented about it.
What you can do relatively easy to verify this assumption:
(a) Obtain a reference to the BeanManager and query it for the relevant bean type (or just for Object to be on the save side), of course you will have to remove #Inject in DomainObjectARepositoryTest in order to get the application started.
(b) Register an extension and listen to ProcessBean to what comes up during the deployment. That would be my suggested way to go, you'll find more information here.
With that outcome you should definitely be able to tell if there are any bean types Repository<E, K extends Serializable & Comparable<K>> hanging around :-)
Would be cool if you'd report back here with the results and also considered filing a Jira issue in the negative case.

Related

Aspect does not trigger around repositories in my application

I want to trigger my aspect for classes annotated with repositories and belonging to my packages, for example this one:
//com.foo.myapp.bar.repositories.dao
#Repository
public class MyRepo extends JpaRepository<MyEntity, String>{
My classes are jpa repositories created like this:
#EnableTransactionManagement
#EnableJpaRepositories(
entityManagerFactoryRef = "firstManagerFactory",
transactionManagerRef = "firstTransactionManager",
basePackages = {"com.foo.myapp.bar.repositories.first.dao"}
)
public class DbConfig {
My aspect is the following but only activates if I leave the repository() pointcut, but if I also specify application packages it doesn't work:
#Pointcut("within(#org.springframework.stereotype.Repository *)")
private void repositoryInvocation() {
// Method is empty as this is just a Pointcut, the implementations are in the advices.
}
#Pointcut("within(com.foo.myapp..*)")
public void applicationPackage() {
// Method is empty as this is just a Pointcut, the implementations are in the advices.
}
#Around("repositoryInvocation() && applicationPackage()") //this && doesn't work, I have to remove the second one
public Object aspectTriggers(ProceedingJoinPoint joinPoint) throws Throwable {
Object result = joinPoint.proceed();
return result;
}
What am I missing?
edit:
I think I got it: problem is that the implementation of the repository does not belong to my application package, but to spring's SimpleJPARepository. It's like the aspect is only working on the implementation, totally ignoring the interface.
I think you do not want
#Pointcut("within(#org.springframework.stereotype.Repository *)")
but rather
#Pointcut("#within(org.springframework.stereotype.Repository)")
Be careful with your pointcut syntax, the two are not the same:
within() describes a package or class name you want to scope/limit your pointcut to.
#within() looks for a type (class) with the given annotation.
You want the latter, not the former.
Edit: On a second thought, actually I see no obvious reason why the first version should not work, even though it is a bit more complicated than the second.
But you said that you had problems with the second pointcut anyway. Are you 100% sure that your repository class really is in a com.foo.myapp (sub) package? No typo in either the package name or the pointcut? Actually, without trying and only looking at it, it should work otherwise.

How to know if a class is an #Entity (javax.persistence.Entity)?

How can I know if a class is annotated with javax.persistence.Entity?
Person (Entity)
#Entity
#Table(name = "t_person")
public class Person {
...
}
PersonManager
#Stateless
public class PersonManager {
#PersistenceContext
protected EntityManager em;
public Person findById(int id) {
Person person = this.em.find(Person.class, id);
return person;
}
I try to do it with instance of as the following
#Inject
PersonManager manager;
Object o = manager.findById(1);
o instanceof Entity // false
however the result is false, shouldn't it be true?
While the existing answers provide a (somehow) working solution, some things should be noted:
Using an approach based on Reflection implies (a) Performance Overhead and (b) Security Restrictions (see Drawbacks of Reflection).
Using an ORM-specific (here: Hibernate) approach risks portability of the code towards other execution environments, i.e., application containers or other customer-related settings.
Luckily, there is a third JPA-only way of detecting whether a certain Java class (type) is a (managed) #Entity. This approach makes use of standardized access to the javax.persistence.metamodel.MetaModel. With it you get the method
Set < EntityType > getEntities();
It only lists types annotated with #Entity AND which are detected by the current instance of EntityManager you use. With every object of EntityType it is possible to call
Class< ? > getJavaType();
For demonstration purposes, I quickly wrote a method which requires an instance of EntityManager (here: em), either injected or created ad-hoc:
private boolean isEntity(Class<?> clazz) {
boolean foundEntity = false;
Set<EntityType<?>> entities = em.getMetamodel().getEntities();
for(EntityType<?> entityType :entities) {
Class<?> entityClass = entityType.getJavaType();
if(entityClass.equals(clazz)) {
foundEntity = true;
}
}
return foundEntity;
}
You can provide such a method (either public or protected) in a central place (such as a Service class) for easy re-use by your application components. The above example shall just give a direction of what to look for aiming at a pure JPA approach.
For reference see sections 5.1.1 (page 218) and 5.1.2 (page 219f) of the JPA 2.1 specification.
Hope it helps.
If the statement
sessionFactory.getClassMetadata( HibernateProxyHelper.getClassWithoutInitializingProxy( Person.class ) ) != null;
is true, than it is an entity.
#NiVer's answer is valid. But, if you don't have a session or sessionFactory at that point you could use Reflection. Something like:
o.getClass().getAnnotation(Entity.class) != null;

JBoss7.1 final 2 counts of IllegalAnnotationExceptions

I'm trying to migrate app from jboss 5.1 to 7.1 and i have error like this Error message which i'm not sure why i get this. if anyone have any idea please help me.
Update: 1
#Stateless
#Remote(PackageService.class)
#Interceptors(CrossContextSpringBeanAutowiringInterceptor.class)
#WebContext(contextRoot="/appname_web_services", urlPattern="/MaintenanceService", authMethod="", secureWSDLAccess=false)
#WebService(
name="MaintenanceService",
targetNamespace = "http://appname.com/web/services",
serviceName = "MaintenanceService")
#SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.WRAPPED)
#HandlerChain(file = "WebServiceHandlerChains.xml")
#TransactionTimeout(10800)
public class MaintenanceServiceBean implements MaintenanceService {
private static final Logger logger = Logger.getLogger( MaintenanceServiceBean.class );
#Resource(mappedName="/ConnectionFactory")
ConnectionFactory connectionFactory;
#Resource(mappedName="topic/manager_system_topic")
javax.jms.Destination systemTopic;
#Autowired
MaintenanceService MigrationService;
#WebMethod
public List<Long> getSoftDeletedPackageIds(Long performedBy) throws Exception {
return MigrationService.getSoftDeletedPackageIds(null);
}
this is the class where i believe it fails.
You are using an interface in your JAXB mappings for which you have not provided enough information to the runtime for it too be able to bind an actual implementation. Without more code included in your question it's hard to recommend a specific solution, but typically you would annotate the included interface with #XmlAnyElement.
You can read through this useful tutorial to determine the best solution for your possible case.

google-gin a provider needs a dependency. NullPointerException BindingsProcessor.java:498

In my GWT application i'm trying to setup a DI mechanism wihich would allow me to have all the commonly necessary stuff at hand everywhere. I'm using google-gin which is an adaptation of guice for GWT. I have an injector interface defined as this:
#GinModules(InjectionClientModule.class)
public interface MyInjector extends Ginjector {
public PlaceController getPlaceController();
public Header getHeader();
public Footer getFooter();
public ContentPanel getContent();
public EventBus getEventBus();
public PlaceHistoryHandler getPlaceHistoryHandler();
}
My injection module is this:
public class InjectionClientModule extends AbstractGinModule {
public InjectionClientModule() {
super();
}
protected void configure() {
bind(Header.class).in(Singleton.class);
bind(Footer.class).in(Singleton.class);
bind(ContentPanel.class).in(Singleton.class);
bind(EventBus.class).to(SimpleEventBus.class).in(Singleton.class);
bind(PlaceController.class).toProvider(PlaceControllerProvider.class).asEagerSingleton();
bind(PlaceHistoryHandler.class).toProvider(PlaceHistoryHandlerProvider.class).asEagerSingleton();
}
}
When calling MyInjector injector = GWT.create(MyInjector.class); i'm gettign the following exception:
java.lang.NullPointerException: null
at com.google.gwt.inject.rebind.BindingsProcessor.createImplicitBinding(BindingsProcessor.java:498)
at com.google.gwt.inject.rebind.BindingsProcessor.createImplicitBindingForUnresolved(BindingsProcessor.java:290)
at com.google.gwt.inject.rebind.BindingsProcessor.createImplicitBindingsForUnresolved(BindingsProcessor.java:278)
at com.google.gwt.inject.rebind.BindingsProcessor.process(BindingsProcessor.java:240)
at com.google.gwt.inject.rebind.GinjectorGeneratorImpl.generate(GinjectorGeneratorImpl.java:76)
at com.google.gwt.inject.rebind.GinjectorGenerator.generate(GinjectorGenerator.java:47)
at com.google.gwt.core.ext.GeneratorExtWrapper.generate(GeneratorExtWrapper.java:48)
at com.google.gwt.core.ext.GeneratorExtWrapper.generateIncrementally(GeneratorExtWrapper.java:60)
at com.google.gwt.dev.javac.StandardGeneratorContext.runGeneratorIncrementally(StandardGeneratorContext.java:647)
at com.google.gwt.dev.cfg.RuleGenerateWith.realize(RuleGenerateWith.java:41)
at com.google.gwt.dev.shell.StandardRebindOracle$Rebinder.rebind(StandardRebindOracle.java:78)
at com.google.gwt.dev.shell.StandardRebindOracle.rebind(StandardRebindOracle.java:268)
at com.google.gwt.dev.shell.ShellModuleSpaceHost.rebind(ShellModuleSpaceHost.java:141)
at com.google.gwt.dev.shell.ModuleSpace.rebind(ModuleSpace.java:585)
at com.google.gwt.dev.shell.ModuleSpace.rebindAndCreate(ModuleSpace.java:455)
at com.google.gwt.dev.shell.GWTBridgeImpl.create(GWTBridgeImpl.java:49)
at com.google.gwt.core.client.GWT.create(GWT.java:97)
The problem is that the PlaceController class actually depends on one of the other dependencies. I've implemented it's provider like this:
public class PlaceControllerProvider implements Provider<PlaceController> {
private final PlaceController placeController;
#Inject
public PlaceControllerProvider(EventBus eventBus) {
this.placeController = new PlaceController(eventBus);
}
#Override
public PlaceController get() {
return placeController;
}
}
what should i change for this to work?
Old question but having the same problem I kept falling here. I finally found the way to know which class is messing during ginjection.
When I launch my app in development mode and put stack to Trace, I noticed there is a step called : "Validating newly compiled units".
Under this, I had an error but I didn't notice it since I had to expand 2 nodes which weren't even in red color.
The error was "No source code available for type com.xxx.xxxx ...", which was due to a bad import on client side which couldn't be converted to Javascript.
Hope this may help other here !
While I'm not actually seeing how the errors you're getting are related to the PlaceController being injected, I do see that the provider is returning a singleton PlaceController even if the provider were not bound as an eager singleton or in a different scope. The correct way to write that provider would be:
public class PlaceControllerProvider implements Provider<PlaceController> {
private final EventBus eventBus;
#Inject
public PlaceControllerProvider(EventBus eventBus) {
this.eventBus = eventBus;
}
#Override
public PlaceController get() {
return new PlaceController(eventBus);
}
}
Let guice handle the scoping i.e. "Letting guice work for you".
Other than that, I almost bet that your problem is due to the use of asEagerSingleton. I recommend you try this with just in(Singleton.class) and I further posit that you didn't really need the singleton to be eager. It seems others had problems with the behavior too, there's some indication that it has to do with overusing asEagerSingleton or misunderstanding the #Singleton annotation in a few cases.
I also got a lot of NullPointerException warnings using GIN 1.x with no real explanation of what happened. When I upgraded to gin 2.0 I was told with high accuracy what the error was. You might be helped by upgrading to the 2.0 version that was released a year after you asked this question.
Had the same problem problem, same trace, and the error was that I used "server" classes in my "client" classes, so GIN can't find these classes.
I mean by "server" and "client" the packages in my project.
Hope this could help

How to make JPA EntityListeners validate the existence of an interface

I am working in J2EE 5 using JPA, I have a working solution but I'm looking to clean up the structure.
I am using EntityListeners on some of the JPA objects I am persisting, the listeners are fairly generic but depend on the beans implementing an interface, this works great if you remember to add the interface.
I have not been able to determine a way to tie the EntityListener and the Interface together so that I would get an exception that lead in the right direction, or even better a compile time error.
#Entity
#EntityListener({CreateByListener.class})
public class Note implements CreatorInterface{
private String message;....
private String creator;
....
}
public interface CreatorInterface{
public void setCreator(String creator);
}
public class CreateByListener {
#PrePersist
public void dataPersist(CreatorInterface data){
SUser user = LoginModule.getUser();
data.setCreator(user.getName());
}
}
This functions exactly the way I want it to, except when a new class is created and it uses the CreateByListener but does not implement the CreatorInterface.
When this happens a class cast exception is thrown somewhere deep from within the JPA engine and only if I happen to remember this symptom can I figure out what went wrong.
I have not been able to figure a way to require the interface or test for the presence of the interface before the listener would be fired.
Any ideas would be appreciated.
#PrePersist
public void dataPersist(Object data){
if (!(data instanceof CreatorInterface)) {
throw new IllegalArgumentException("The class "
+ data.getClass()
+ " should implement CreatorInterface");
}
CreatorInterface creatorInterface = (CreatorInterface) data;
SUser user = LoginModule.getUser();
creatorInterface.setCreator(user.getName());
}
This does basically the same thing as what you're doing, but at least you'll have a more readable error message indicating what's wrong, instead of the ClassCastException.