Is it possible to annotate a method with #TransactionAttribute in BMT EJB? - java-ee-6

I came across a piece of code where the bean implementation class has #TransactionManagement(TransactionManagementType.BEAN) annotation wherein methods are annotated with CMT #TransactionAttribute. Is is valid?
Can an EJB with BMT persistence use CMT transaction annotation? What will be the behavior at runtime?
Though javadoc http://docs.oracle.com/javaee/6/api/javax/ejb/TransactionAttribute.html says that "It can only be specified if container managed transaction demarcation is used.", specifying it doesn't throw any compilation error. Does it mean that jvm simply ignores it at runtime?
#Stateless( mappedName = "Abc")
#Remote("AbcRemote.class")
#Local("AbcLocal.class")
#TransactionManagement(TransactionManagementType.BEAN)
public class AbcBean implements AbcLocal, AbcRemote{
#Resource
private UserTransaction utx;
#PersistenceUnit
private EntityManagerFactory emf;
#Override
#TransactionAttribute(TransactionAttributeType.REQUIRED)
public Abc getAlpbabets(String name) {
EntityManager em = null;
try {
em = emf.createEntityManager();
}
catch (RuntimeException re) {
throw re;
}
finally {
}
}
}

If you use CMT, then #TransactionAttribute(TransactionAttributeType.REQUIRED) would tell the container to check for an existing transaction and open one if there is none.
But if you use BMT, then it's your responsibility to do such a thing, so there's no one to observe the annotation above. Since it is still syntactically correct and the class is available, there is no need for the JVM to complain about.
Concerning ignoring annotations, there's a hint in the answer to this question.

Related

Using a Producer Method To Choose a Bean Implementation

I followed the example on here for dynamically selecting the implementation to inject during run time. I then try to implement it based on my understanding but my code always return the default implementation;
Here is my code
#Stateless
public class MemberRegistration {
#Inject
private Logger log;
#Inject
private EntityManager em;
#Inject
private Event<Member> memberEventSrc;
#Inject
#Switch
IHandler handler;
private int handlerValue;
public String testCDI(int value) {
handlerValue = value;
log.info("handling " + value);
log.info("handling " + handlerValue);
return handler.handle();
}
#Produces
#RequestScoped
#Switch
public IHandler produceHandler(#New Handler0 handler0,
#New Handler1 handler1) {
log.info("Calling producer method with handler: "+handlerValue);
switch (handlerValue) {
case 1:
log.info("returning one");
return handler1;
case 0:
log.info("returning 0");
return handler0;
default:
log.info("returning default");
return handler1;
}
}
}
When i call the method testCDI I then update the handlerValue so that my producer method can use that value. What am I missing here to ensure that the producer method is called when the right value is available?
The code is running on Wildfly 8.2.0
The instance injected isn't going to be resolved when you call the method, but at the time of injection of the bean (the stateless session bean in this case). As a result, handlerValue will be 0.
You can however use an Instance<IHandler> to defer the injection. Use an annotation literal instead of your switch to do something like
#Inject
#Any
private Instance<IHandler> handlerInst
Then in your code
IHandler handler = handlerInst.select(new SwitchLiteral(value)).get();
then do work against that guy, but in your producer you need to use the InjectionPoint class to read the Switch annotation represented by the SwitchLiteral
You are running into cycling dependency here with your simplified code. Fields injected with plain #Inject need to be resolved BEFORE MemberRegistration is created, but handler field can only be created with a producer method AFTER MemberRegistration is created (beans with producer methods are created according to same rules as other CDI beans).
There are 2 solutions:
Either you create a separate HandlerProducer class, which will contain produceHandler() method and also handlerValue field. You should mark the class as #ApplicationScoped in order to reuse the same instance all over.
Or you need not only to produce IHandler dynamically, but also use (inject it) dynamically only when really needed in the MemberRegistration - this way handler is produced not BEFORE MemberRegistration is created, but after or never if not required. You do this by injecting Instance object and then use its get() method to retrieve handler when needed. Anyway, I am not sure if CDI will create a new instance every time, or reuse existing EJB. Scopes of EJBs and plain CDI beans are completely different and in general, I would not use an EJB as a bean with producer methods. It is better to always create a separate bean for producer methods, as in solution 1.
Example for solution 2 follows:
#Inject
#Switch
Instance<IHandler> handlerInjector;
private int handlerValue;
public String testCDI(int value) {
handlerValue = value;
log.info("handling " + value);
log.info("handling " + handlerValue);
return handlerInjector.get().handle();
}

Why transaction can't commit in a self-invoked ejb method with #REQUIRES_NEW Annotation

First I want to explain my self-invoked ejb method in this situation. I have a stateful session bean with a method which starts a new transaction (Annotated by #REQUIRES_NEW). To invoke this method inside the bean itself and make the annotation effective, I use SessionContext#getBusinessObject() to achieve the effect of #EJB (#EJB here causes stackoverflow?!). My code is shown below:
#Stateful
#Local
public class TransactionTest implements ITransactionTest {
#PersistenceContext(unitName="Table",Type=PersistenceContextType.EXTENDED)
private EntityManager manager;
#Resource
SessionContext sc;
ITransactionTest me;
#PostConstruct
public void init(){
me = this.sc.getBusinessObject(ITransactionTest.class);
}
public void generateRecord(int i) throws RuntimeException{
Record record = new Record();
record.setId(i+"");
record.status(1);
manager.persist(record);
manager.flush(); //If not flush, result is correct. Why?
me.updateRecord(i);
}
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void updateRecord(int i) throws RuntimeException{
try {
Record record = manager.find(Record.class, i+"");
record.setStatus(2);
manager.flush();
} catch(Exception e) {
e.printStackTrace();
throw new RuntimeException();
}
}
}
While,generateRecord() runs properly. The console shows it executes 'insert' and 'update' HQL without any exception (I use Hibernate as JPA provider). However, the 'update' result doesn't appear in the database. Why? Does updateRecord() commit correctly?
Also, I try it in two altenative ways: First is invoking generateRecord() (it will no longer invoke updateRecord()) and updateRecord() consecutively in another bean. It can give me the right result.
The second is removing the first flush(). Then both 'insert' and 'update' HQL will be executed at the second flush(). This method can also produce right result.
My program is running under JBOSS 6.1.0-Final and database is Oracle.
Best Regards,
Kajelas

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

Injecting generic Beans with CDI/Weld

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.

JPA default persistence unit

I get exception "There is no default persistence unit in this deployment." can I somehow mark unit as default?(I have only one persistence unit, so Id rather not call it by name)
No, you have to call PU's by name.
You are probably doing it through code rather than letting the container manage it. In which case you have to specify by name.
My unit test code has this code block to do this.
#Before
public void createEntityManagerFactory() throws IOException {
final Properties p = new Properties();
p.load(getClass().getResourceAsStream("/inmemory.properties"));
emf = Persistence.createEntityManagerFactory("default", p);
}
However, my application code looks like this.
/**
* Injected persistence context.
*/
#PersistenceContext
private EntityManager em;