Getting Started with CDI part 2 – Injection
In part 1, we looked at creating a JEE 6 application with Netbeans using JSF and CDI running on Glassfish. Now we’ll take a closer look at using CDI for managing dependencies in a Java EE 6 environment.
Read Part 1
Read Part 2
Read Part 3
Last Time
Last time we looked at setting up the development environment and creating our EE6 application in Netbeans and deploying it to Glassfish v3. This time, we’ll skip straight to writing code which can be put into either a new Netbeans project using the previous tutorial, or you can use the existing project and just add the new code.
The ‘I’ in CDI
CDI is an API for injecting contexts and dependencies which is the part we’ll turn our attention to now. In Seam and Spring dependencies worked mostly by naming beans and binding them to their injection points by their name. So far we have only referenced a managed bean by name from the JSF page when we defined the name for the bean using the @Named
annotation. The primary role of the @Named
annotation is to define the bean for the purpose of resolving EL statements within the application, usually through the JSF EL resolvers. Injection could be performed by using names, but this was not how injection in CDI was meant to work since CDI gives us a much richer way to express injection points and the beans to be injected into them.
Let’s look at an example which is somewhat contrived. We have a dao that returns a list of objects that need validating, and for invalid ones, we take a certain action. Here’s the definition for the item.
package eedemo; public class Item { private int value; private int limit; @Override public String toString() { return super.toString() + String.format(" [Value=%d, Limit=%d]", value,limit); } /* getters and setters omitted */ }
The ItemDao
interface defines how we get the list of item objects. In this test application we anticipate using multiple implementations so we will code to interfaces.
public interface ItemDao { List<Item> fetchItems(); }
The ItemProcessor
is our main class that we will inject our beans into and execute the process from. For now, we will start with the Dao and look at how we will inject it into our processor bean.
import java.util.List; import javax.inject.Named; import javax.enterprise.context.RequestScoped; @Named("itemProcessor") @RequestScoped public class ItemProcessor { private ItemDao itemDao; public void execute() { List<Item> items = itemDao.fetchItems(); for (Item item : items) { System.out.println("Found item "+item); } } }
We’ll start with a simple Dao that just creates a list of items and returns a fixed list of items.
public class DefaultItemDao implements ItemDao { public List<Item> fetchItems() { List<Item> results = new ArrayList<Item>(); results.add(new Item(34, 7)); results.add(new Item(4, 37)); results.add(new Item(24, 19)); results.add(new Item(89, 32)); return results; } }
In order to inject the DefaultItemDao
into our ItemProcessor
we add the javax.inject.Inject
annotation to the ItemDao
field to indicate that this field is an injection point.
@Named("itemProcessor") @RequestScoped public class ItemProcessor { @Inject private ItemDao itemDao; ... }
Finally, we need some way to call the execute()
ItemProcessor. We can run this in a SE environment, but for now we’ll keep it in a JSF page. We’ll add a new page with a button to call the execute method called process.xhtml
.
<?xml version='1.0' encoding='UTF-8' ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"> <h:head> <title>Item Processor</title> </h:head> <h:body> <h:form> <h:commandButton action="#{itemProcessor.execute}" value="Execute"/><br/> </h:form> </h:body> </html>
If you open up the page at http://localhost:8080/ee6demo/faces/process.xhtml you will see just a button that when clicked lists the items from our default Dao implementation in the console.
INFO: Found item eedemo.Item@23cbc6 [Value=34, Limit=7] INFO: Found item eedemo.Item@a40279 [Value=4, Limit=37] INFO: Found item eedemo.Item@19e6292 [Value=24, Limit=19] INFO: Found item eedemo.Item@1597bc4 [Value=89, Limit=32]
We created a class which implements the ItemDao
interface and when the application was deployed our managed beans in the module were processed by the CDI implementation (again because of the beans.xml
file in the module. Our Inject
annotation specifies that we want to inject a managed bean into that field and the only thing we know about the bean to inject is that it must implement ItemDao
or some subtype of that interface. In this case, the DefaultItemDao
class fits the bill perfectly.
Let’s say we add another Dao class to our application which also implements the ItemDao
interface, now the choice isn’t so clear as to which bean we want to inject.
public class AnotherItemDao implements ItemDao { public List<Item> fetchItems() { List<Item> results = new ArrayList<Item>(); results.add(new Item(99, 9)); return results; } }
We now have two classes the implement this interface and predictably, Weld gives us an ambiguous dependency error meaning that it cannot determine what bean to use for that injection point. Most, if not all of the errors that can occur with regards to CDI injection in Weld are reported at deployment time, even down to whether beans are missing a Serializable implementation.
Caused by: org.jboss.weld.DeploymentException: Injection point has ambiguous dependencies. Injection point: field eedemo.ItemProcessor.itemDao; Qualifiers: [@javax.enterprise.inject.Default()]; Possible dependencies: [eedemo.AnotherItemDao, eedemo.DefaultItemDao]
We could make our itemDao
field in the item processor a type that matches one of the implementation types (AnotherItemDao
or DefaultItemDao
) since it would then match one and only one class type. However, then we would lose the benefits of coding to an interface and find it harder to change implementations without changing the field type. A better solution is to instead look at CDI Qualifiers.
Qualifiers
A CDI qualifier is an annotation that can be applied at the class level to indicate the kind of bean the class is, and also at the field level (among other places) to indicate what kind of bean needs to be injected at that point.
When CDI inspects an injection point to find a suitable bean to inject it takes not only the class type into account, but also any qualifiers. Without knowing it, we have already used one qualifier which is the default qualifier called @Any
. Let’s create a @Demo
qualifier which we can apply to our DefaultItemDao
implementation and also to the injection point.
package eedemo.qualifier; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.ElementType.METHOD; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import javax.inject.Qualifier; @Retention(RetentionPolicy.RUNTIME) @Target({FIELD,METHOD,PARAMETER,TYPE}) @Qualifier public @interface Demo { }
First, we’ll add this qualifier to our default dao implementation at the class level.
@Demo public class DefaultItemDao implements SomeDao { public List<Item> fetchItems() { .. ..
If you save and deploy this file now, you may notice that we don’t have any errors, and if you go to the web page and click the execute button, you can see that in the console, it displays the list of items from the AnotherItemDao
dao (remember we annotated the DefaultItemDao
implementation but not the injection point). By adding the Demo
qualifier to the default dao implementation, we made the other implementation a more suitable match for the injection point as it matched on type and on qualifiers and the DefaultItemDao
has a qualifier that is not on the injection point making it less suitable.
If we add the Demo
annotation to the injection point and deploy it, when we click our button we use the default implementation again. This is because we are matching based on type and qualifiers and the DefaultItemDao
is the only bean with both the correct type and the Demo
annotation.
Alternative Injection Methods
There are multiple ways to define an injection point on the injected class. So far we have annotated the fields that will reference the injected object. You do not need to provide getters and setters for field injection. If we wish to create immutable managed beans with final fields, we can use injection in the constructor by annotating the constructor with the Inject
annotation. We can then apply any annotations to constructor parameters to qualify beans for injection (of course, each parameter has a type that can assist in qualifying beans for injection). A bean may only have one constructor with injection points defined, but it may implement more than one constructor.
@Named("itemProcessor") @RequestScoped public class ItemProcessor { private final ItemDao itemDao; @Inject public ItemProcessor(@Demo ItemDao itemDao) { this.itemDao = itemDao; } }
We can also call an inialization method which can be passed the beans to be injected.
@Named("itemProcessor") @RequestScoped public class ItemProcessor { private ItemDao itemDao; @Inject public void setItemDao(@Demo ItemDao itemDao) { this.itemDao = itemDao; } }
While in the above case we used the setter method for initialization we can create any method and use it for initialization with as many beans as we want in the method call. We can also have multiple initialization methods in a bean.
@Inject public void initBeans(@Demo ItemDao itemDao,@SomeQualifier SomeType someBean) { this.itemDao = itemDao; this.bean = someBean; }
The same rules apply to bean matching regardless of how the injection point is defined, it will try and find the best match based on type and qualifiers and will fail on deployment if there are multiple matching beans or no matching beans for an injection point.
Let’s look at the other aspects of our application, we get a list of items, iterate through them and test each one and if it fails that test, we pass it on to an error handler. We’ll create an ItemValidator
interface to determines whether an item is valid or not.
public interface ItemValidator { boolean isValid(Item item); }
We’ll expand our ItemProcessor
class to incorporate the new feature.
@Named("itemProcessor") @RequestScoped public class ItemProcessor { @Inject @Demo private ItemDao itemDao; @Inject private ItemValidator itemValidator; public void execute() { List<Item> items = itemDao.fetchItems(); for (Item item : items) { System.out.println("Item = "+item+" valid = "+itemValidator.isValid(item)); } } }
Our first implementation will be DefaultItemValidator
which will simply test the limit against the value.
public class DefaultItemValidator implements ItemValidator { public boolean isValid(Item item) { return item.getValue() < item.getLimit(); } }
If we save our changes, go to our web page and click our button, in the console you will see that our items are being validated and the only valid item is where the value is less than the limit.
INFO: Item = eedemo.Item@25dd89 [Value=34, Limit=7] valid = false INFO: Item = eedemo.Item@1f37ca2 [Value=4, Limit=37] valid = true INFO: Item = eedemo.Item@7b8d67 [Value=24, Limit=19] valid = false INFO: Item = eedemo.Item@18075da [Value=89, Limit=32] valid = false
Now lets consider the scenario where we have a deployment to a different site that is more relaxed and considers an item invalid only if the value is more than twice the limit. We may want to have another bean that implements the validator interface for that logic.
public class RelaxedItemValidator implements ItemValidator { public boolean isValid(Item item) { return item.getValue() < (item.getLimit() * 2); } }
Now we have an ambiguous dependency problem since we have two classes implementing the same interface. The only difference is based on deployment so for most deployments, we want to use the default, but for one deployment, we want to use the relaxed implementation. CDI offers the use of the Alternative
annotation which lets you package multiple beans that match an injection point without ambiguity errors, and the bean to use is defined in the beans.xml
. This means you can deploy both implementations in the same module with the only difference being the beans.xml definition which can change over different deployments.
@Alternative public class DefaultItemValidator implements ItemValidator { public boolean isValid(Item item) { return item.getValue() < item.getLimit(); } }
and
@Alternative public class RelaxedItemValidator implements ItemValidator { public boolean isValid(Item item) { return item.getValue() < (item.getLimit() * 2); } }
If we deploy our application now, we will get an unsatisfied dependency error since we defined the two matching beans as alternative but we didn’t enable either of them in the beans.xml
file.
<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"> <alternatives> <class>eedemo.RelaxedItemValidator</class> </alternatives> </beans>
This tells CDI that for this deployment we want to use the RelaxedItemValidator
. You can think of the alternative annotation as effectively disabling the bean making it unavailable for injection, but allowing the implementation to be packaged with the other beans. Adding it as an alternative in the beans.xml
file effectively enables the bean making it available for injection. By moving this type of metadata to the beans.xml
file, we can bundle different versions of the file with different deployments.
Handling Invalid Items
Continuing the example, invalid items are sent to the ItemErrorHandler
as they are discovered.
public interface ItemErrorHandler { void handleItem(Item item); }
Let’s start by implementing a fake handler that saves the item details to a file. We want to open the file before we start handling items, leave it open for the duration of the process as we add content to the file, and then close the file when we are done with our processing. We could manually add initProcess()
and finishProcess()
methods to the error reporter bean, but then we couldn’t code to the interface since the caller would need to know about those class specific methods. We could add those same methods to the ItemErrorReporter
interface but then we would have to unnecessarily implement those methods in every class that implements that interface. Instead, we can use some of the lifecycle annotations from the Managed Bean spec to call methods on the bean at certain points in the bean lifecycle. A PostConstruct
annotated method is called when the bean has been constructed and any dependencies the bean has have been injected. Likewise, a PreDestroy
annotated method is called just before the bean is disposed of by the container.
public class FileErrorReporter implements ItemErrorHandler { @PostConstruct public void init() { System.out.println("Creating file error reporter"); } @PreDestroy public void release() { System.out.println("Closing file error reporter"); } public void handleItem(Item item) { System.out.println("Saving "+item+" to file"); } }
Our final change is to add the item error handling into our ItemProcessor
bean.
@Named("itemProcessor") @RequestScoped public class ItemProcessor { @Inject @Demo private ItemDao itemDao; @Inject private ItemValidator itemValidator; @Inject private ItemErrorHandler itemErrorHandler; public void execute() { List<Item> items = itemDao.fetchItems(); for (Item item : items) { if (!itemValidator.isValid(item)) { itemErrorHandler.handleItem(item); } } } }
When we run this from our browser we see the following in the console ;
INFO: Creating file error reporter INFO: Saving eedemo.Item@d8b01e [Value=34, Limit=7] to file INFO: Saving eedemo.Item@12a5e8 [Value=89, Limit=32] to file INFO: Closing file error reporter
Next Time
Different application deployments might use different rules for handling invalid items. such as rejecting the item, to sending notifications to individuals or just flagging them or listing them in an output file. In addition, we may want to do a combination of these (reject an order, send email to the sales rep, and list it in a file).
One great way to handle this kind of multi-faceted problem is using events which we’ll look at next time.
Click to view getting started with jsf 2.0 and CDI part 3
29 thoughts on “Getting Started with CDI part 2 – Injection”
Comments are closed.
Hi, is there an equivalent of Seam’s @In(“#{someExpression}”) in CDI? I would like to inject the client’s IP address inside a service (#{facesContext.externalContext.request.remoteAddr}) but can’t find a way to do that.
thanks
@Xavier, you just have to think in terms of producing what you want, qualifying it, then injecting it in a type-safe way or exposing the produced result directly to the EL.
public class RemoteAddressProducer {
@Produces
@RequestScoped
@RemoteAddress
String resolveRemoteAddress() {
return ((HttpServletRequest) FacesContext.getCurrentInstance()
.getExternalContext().getRequest()).getRemoteAddr();
}
}
In the above case, you can inject the result as follows:
@Inject @RemoteAddress String remoteAddress;
very nice introduction. thanks for sharing! can’t wait for part 3 to come 🙂
Very good indeed. I’m very excited with all the Java EE 6 features, specially CDI.
I think Netbeans can also help here, with an option to create a new kind of file with type producer (“new producer”) and add all this boilerplate code. Another suggestion for the NB team as they are working on a CDI support module, as they said.
Anything that makes our lives easier is very welcome and I think Java EE 6 and CDI together with NB is great.
And a “new qualifier” too to reduce the need for all those copying and pasting operations.
Hi Andy,
I’m VERY new to Java 6’s CDI (as in ‘this afternoon’) but I came across your site as a solution to the missing beans.xml in Glassfish (thanks for that 😉 ).
My question really, coming from a reasonable Spring background, is why was the Qualifier annotation mechanism chosen as a means of ‘naming’ different instances of Class? It appears to simply add unnecessary [annotation] code, but maybe I’m missing something?
The @Named annotation is closer to what is required, but, from what little I’ve read (this afternoon), that seems to only relate to accessing the bean via a JSF/JSP-like EL script (correct?). Why didn’t the authors of CDI/Weld not simply add a ‘bean-name’ attribute to the @Produces & @Inject attributes, and then use typing to attempt to avoid conflicts?
If the aim is to be as DRY as possible, wouldn’t the above suggestion sound better?
Apologies for using your site like a forum.
Once again, thanks for the articles.
Cheers
Big Rich
Hi again,
Been back to my code and I need to correct my thoughts regarding the usage of the ‘@Named(“someNamedBean”)’ annotation. Turns out that you CAN use it in conjunction with @Inject/@Produces, within normal Java code, to access differing instances of the same Class, for example. Thus:
@Inject @Named(“some”)
The same use of @Named(“..”) should also be employed at the @Produces end.
This appears to get around my reservations concerning the proliferation of surplus bean Qualifier annotations (interface) declarations (although they might be more IDE/code completion friendly).
The ‘light in the tunnel’ for the user-defined annotations might come in the form of Qualifier ‘members’ which appear to be adding naming to the identifying qualifier/annotation, meaning that one annotation may be used to ‘mark’ differing bean instances. Please see the [Weld R.I.] documentation at:
http://docs.jboss.org/weld/reference/1.0.0/en-US/html/injection.html#d0e1237
Cheers
Big Rich
Hey Rich,
Yes, you can use named as a qualifier on produces and inject the same as you use any other kind of qualifier. Typically though, named is only used for exposing the bean with a name in EL.
By using qualifier annotations, the injection becomes type safe as opposed to being based only on a string name. The @Named annotation is just another qualifier with a string member to make it unique, it is only special in that it is the one used to expose the bean externally to EL.
Cheers,
Andy
In alternative injection method, the injection on constructor fails : weld refuse to deploy webapp.
@javax.inject.Named(“itemProcessor”)
@javax.enterprise.context.RequestScoped
public class ItemProcessor
{
private ItemDao itemDao;
@javax.inject.Inject
public ItemProcessor(@Demo ItemDao itemDao)
{
this.itemDao = itemDao;
}
}
The error message is :
Caused by: javax.enterprise.inject.UnproxyableResolutionException: Normal scoped bean org.jboss.weld.bean-/C:/Documents and Settings/fred/workspace/.metadata/.plugins/com.sun.enterprise.jst.server.sunappsrv92/domain1/eclipseApps/MyFirstWebApp/-ManagedBean-class mycompany.first.bean.ItemProcessor is not proxyable
at org.jboss.weld.Validator.validateBean(Validator.java:85)
at org.jboss.weld.Validator.validateRIBean(Validator.java:100)
at org.jboss.weld.Validator.validateBeans(Validator.java:282)
at org.jboss.weld.Validator.validateDeployment(Validator.java:268)
at org.jboss.weld.bootstrap.WeldBootstrap.validateBeans(WeldBootstrap.java:389)
at org.glassfish.weld.WeldDeployer.event(WeldDeployer.java:180)
It’s curious because ItemProcessor class is not a normal scoped bean, but a request scoped bean.
How to do ?
Again me.
I tested next example with injection on setter :
@javax.inject.Inject
public void setItemDao(@Demo ItemDao itemDao)
{
this.itemDao = itemDao;
}
and it worked fine. Really don’t understand why it fails for constructor.
I use Glassfish Tools Bundle for Eclipse 1.2 (Glassfish 3)
Interesting, I had a look at your example, and off the top of my head, I’m not sure. I do know there are a couple of kinks that still need to be worked out, for example, injecting a stateless bean causes problems because the bean cannot be serialized, but if it’s a stateless bean it doesn’t need to be serialized. This seems sort of similar, but different. What is the scope of the ItemDao?
Cheers,
Andy
Hi Andy,
Thanks for this nice introduction to CDI.
I came across your article after deciding to try converting a working JSF @ManagedBean to a CDI @Named bean. It wouldn’t work properly so I did Google search to try and find some help.
After starting to work through your example the penny dropped. The @SessionScoped annotation was still using the JSF javax.faces.bean.SessionScoped import instead of the CDI javax.enterprise.context.SessionScoped import.
I just note this here in case anyone else also encounters this problem.
Cheers,
Nic
Yes, you do need to be careful since many of the annotations have similar names. It is really an annoyance that I don’t believe will go away any time soon.
However, thanks for posting, if nothing else, it might be a good idea to include some of the import statements in my code examples,
Thanks,
Andy
Andy,
Having the same problem as Fred has with not being able to do injection into a constructor:
“ItemProcessor is not proxyable”
I am running glassfish v3 in Netbeans 6.8 IDE.
in the case above ItemProcessor is request scoped.
If I change scope to session I see a different error involving the bean not being passivatable.
… so, after making beans serializable, the passivation error no longer happens for session scoped ItemProcessor, but error “eedemo.ItemProcessor is not proxyable” is seen, as in the request scope case. It just doesn’t like constructor injection.
Is the item processor a stateless bean? If so, take off the @Stateless annotation. There is a problem with Weld 1.0 (and maybe 1.0.1) where stateless beans were considered not proxyable which is wrong because they don’t need to be proxied :
Here’s my post about it on the seam framework web site.
http://seamframework.org/Community/ProblemsWithStatelessBeansInWeldCR101CR2
You should be ok if you just remove the stateless annotation making it a non-EJB bean
Cheers,
Andy Gibson
Thanks for the reply. Nope, it is not annotated @Stateless. Until I changed the bean to SessionScope I was copying and pasting from your examples, too. Go figure…
Maybe I am just confused or that I am very new to CDI, so the advantage of Qualifier is that it is typesafe (can apply to interface instead of using names which only applies to implementation)..
so we basically need to create multiple qualifers (meaning multiple classes) for each implementations of the interface we might want to inject?
This does seem kinda inconvenient..
Hey Herman,
Both type and and Qualifiers are used to match beans to injection points so a qualifier is just an additional criteria in case you have beans that implement the same interface.
For example, if you have multiple data source and inject the entity manager, you could qualify one with @WebStoreDb and the other with @DataWarehouseDb. Without a qualifier, we don’t know which to use where.
Btw, Thanks Andy for this article, it is very informative and easy to understand, i was having a hard time learning just by reading the Weld Docs
You might also want to try out a set of Maven Archetypes I just released which in addition contains the usual starter projects, also has a project that implements a CRUD demo with just out-of-the-box Java EE 6.
You can find it at http://www.fluttercode.com/projects/knappsack/
Dear Andy,
How can I fix this error?
An Error Occurred:
Um erro ocorreu ao realizar a inje??o de recurso no bean gerenciado emprestimoController
+- Stack Trace
com.sun.faces.mgbean.ManagedBeanCreationException: Um erro ocorreu ao realizar a inje??o de recurso no bean gerenciado emprestimoController
at com.sun.faces.mgbean.BeanBuilder.injectResources(BeanBuilder.java:211)
at com.sun.faces.mgbean.BeanBuilder.build(BeanBuilder.java:103)
at com.sun.faces.mgbean.BeanManager.createAndPush(BeanManager.java:405)
at com.sun.faces.mgbean.BeanManager.create(BeanManager.java:267)
at com.sun.faces.el.ManagedBeanELResolver.getValue(ManagedBeanELResolver.java:86)
at javax.el.CompositeELResolver.getValue(CompositeELResolver.java:175)
at com.sun.faces.el.FacesCompositeELResolver.getValue(FacesCompositeELResolver.java:72)
at com.sun.el.parser.AstIdentifier.getValue(AstIdentifier.java:99)
at com.sun.el.parser.AstValue.getValue(AstValue.java:158)
at com.sun.el.parser.AstEqual.getValue(AstEqual.java:54)
at com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:219)
at org.jboss.weld.el.WeldValueExpression.getValue(WeldValueExpression.java:71)
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:102)
at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:190)
at javax.faces.component.UIComponentBase.isRendered(UIComponentBase.java:416)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1607)
at javax.faces.render.Renderer.encodeChildren(Renderer.java:168)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:848)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1613)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1616)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1616)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:380)
at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:126)
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:273)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:127)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:313)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1523)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:279)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:188)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:641)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97)
at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:85)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:185)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:325)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:226)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:165)
at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:791)
at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:693)
at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:954)
at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:170)
at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:135)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:102)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:88)
at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76)
at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53)
at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57)
at com.sun.grizzly.ContextTask.run(ContextTask.java:69)
at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:330)
at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:309)
at java.lang.Thread.run(Thread.java:662)
Caused by: com.sun.faces.spi.InjectionProviderException: com.sun.enterprise.container.common.spi.util.InjectionException: Exception attempting to inject Remote ejb-ref name=jpa.entities.EmprestimoController/ejbFacade,Remote 3.x interface =jpa.entities.EmprestimoFacade,ejb-link=null,lookup=null,mappedName=,jndi-name=jpa.entities.EmprestimoFacade,refType=Session into class jpa.entities.EmprestimoController
at org.glassfish.faces.integration.GlassFishInjectionProvider.inject(GlassFishInjectionProvider.java:98)
at com.sun.faces.mgbean.BeanBuilder.injectResources(BeanBuilder.java:205)
… 51 more
Caused by: com.sun.enterprise.container.common.spi.util.InjectionException: Exception attempting to inject Remote ejb-ref name=jpa.entities.EmprestimoController/ejbFacade,Remote 3.x interface =jpa.entities.EmprestimoFacade,ejb-link=null,lookup=null,mappedName=,jndi-name=jpa.entities.EmprestimoFacade,refType=Session into class jpa.entities.EmprestimoController
at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl._inject(InjectionManagerImpl.java:614)
at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.inject(InjectionManagerImpl.java:384)
at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.injectInstance(InjectionManagerImpl.java:168)
at org.glassfish.faces.integration.GlassFishInjectionProvider.inject(GlassFishInjectionProvider.java:94)
… 52 more
Caused by: javax.naming.NamingException: Lookup failed for ‘java:comp/env/jpa.entities.EmprestimoController/ejbFacade’ in SerialContext [Root exception is javax.naming.NamingException: Exception resolving Ejb for ‘Remote ejb-ref name=jpa.entities.EmprestimoController/ejbFacade,Remote 3.x interface =jpa.entities.EmprestimoFacade,ejb-link=null,lookup=null,mappedName=,jndi-name=jpa.entities.EmprestimoFacade,refType=Session’ . Actual (possibly internal) Remote JNDI name used for lookup is ‘jpa.entities.EmprestimoFacade#jpa.entities.EmprestimoFacade’ [Root exception is javax.naming.NamingException: Lookup failed for ‘jpa.entities.EmprestimoFacade#jpa.entities.EmprestimoFacade’ in SerialContext [Root exception is javax.naming.NameNotFoundException: jpa.entities.EmprestimoFacade#jpa.entities.EmprestimoFacade not found]]]
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:442)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl._inject(InjectionManagerImpl.java:513)
… 55 more
Caused by: javax.naming.NamingException: Exception resolving Ejb for ‘Remote ejb-ref name=jpa.entities.EmprestimoController/ejbFacade,Remote 3.x interface =jpa.entities.EmprestimoFacade,ejb-link=null,lookup=null,mappedName=,jndi-name=jpa.entities.EmprestimoFacade,refType=Session’ . Actual (possibly internal) Remote JNDI name used for lookup is ‘jpa.entities.EmprestimoFacade#jpa.entities.EmprestimoFacade’ [Root exception is javax.naming.NamingException: Lookup failed for ‘jpa.entities.EmprestimoFacade#jpa.entities.EmprestimoFacade’ in SerialContext [Root exception is javax.naming.NameNotFoundException: jpa.entities.EmprestimoFacade#jpa.entities.EmprestimoFacade not found]]
at com.sun.ejb.EjbNamingReferenceManagerImpl.resolveEjbReference(EjbNamingReferenceManagerImpl.java:174)
at com.sun.enterprise.container.common.impl.ComponentEnvManagerImpl$EjbReferenceProxy.create(ComponentEnvManagerImpl.java:1040)
at com.sun.enterprise.naming.impl.GlassfishNamingManagerImpl.lookup(GlassfishNamingManagerImpl.java:688)
at com.sun.enterprise.naming.impl.GlassfishNamingManagerImpl.lookup(GlassfishNamingManagerImpl.java:657)
at com.sun.enterprise.naming.impl.JavaURLContext.lookup(JavaURLContext.java:148)
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:428)
… 57 more
Caused by: javax.naming.NamingException: Lookup failed for ‘jpa.entities.EmprestimoFacade#jpa.entities.EmprestimoFacade’ in SerialContext [Root exception is javax.naming.NameNotFoundException: jpa.entities.EmprestimoFacade#jpa.entities.EmprestimoFacade not found]
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:442)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
at com.sun.ejb.EjbNamingReferenceManagerImpl.resolveEjbReference(EjbNamingReferenceManagerImpl.java:169)
… 62 more
Caused by: javax.naming.NameNotFoundException: jpa.entities.EmprestimoFacade#jpa.entities.EmprestimoFacade not found
at com.sun.enterprise.naming.impl.TransientContext.doLookup(TransientContext.java:197)
at com.sun.enterprise.naming.impl.TransientContext.lookup(TransientContext.java:168)
at com.sun.enterprise.naming.impl.SerialContextProviderImpl.lookup(SerialContextProviderImpl.java:58)
at com.sun.enterprise.naming.impl.LocalSerialContextProviderImpl.lookup(LocalSerialContextProviderImpl.java:101)
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:430)
… 64 more
Can’t really tell what the problem is but It looks like you are trying to inject a remote session bean which can’t be done directly in CDI. To do so, you need to inject the EJB using @EJB and then push that out using produced. I’ve never done it, but it should look something like :
This code goes in some utility or factory bean. In your business logic bean, you can then use :
The injection point will use the producer to provide the value to the injection point. Again, I’ve not tried this and this code is off the top of my head. Search the web for CDI and remote beans or consult the 299 spec to get a better idea if this is your problem.
Cheers,
Andy Gibson
Hi Andy
I am trying – without success 🙁 – to inject a PersistenceContext (using @PersistenceContext) in DAO’s:
//@ManagedBean
public class JpaItemDao implements ItemDao {
@PersistenceContext(unitName=”myUnit”)
private EntityManager em;
public List fetchItems() {
// use em to retrieve from db
}
}
But is does not work (em is not set), even with the addition of javax.annotation.ManagedBean…
(running in GF 3.1)
Do you think it is possible ?
Could be use @Inject isof @PersistenceContext ?
Regards,
Bernard, Belgium
(running in GlassFish 3.1)