JSF ClassNotFoundException in EJB module on JBoss EAP 6.1 - jsf

I'm in the middle of porting a JSF 2.1 application to Jboss EAP 6.1 (JBoss AS 7.2). The application runs smoothly on Glassfish 3.1, and Weblogic 12c. Moreover a slightly similar application was ported successfully.
The problem occurs in a specific EJB singleton. In this, I have a method with #PostConstruct annotation, which runs at startup and fills a List with SelectItems. During deploy, a java.lang.ClassNotFoundException exception is thrown, which says JBoss can't find the javax.faces.model.SelectItem class.
If I comment out the method, everything is fine. The SelectItem class is used in some other beans in the web module without any problem.
My question is: Is there any known reason for this behaviour? Do I need some special configuration to use classes from the javax.faces package in an EJB module, running on JBoss?
JSF is not packaged with the EAR, so the application uses the server's implementation.
Thank you!

You've there a design mistake. The business service (EJB) tier is not supposed to have any web (JSF) tier related dependencies. Having javax.faces.* imports in an EJB class is in first place already wrong. It makes the business service unreusable across different web tiers such as JAX-RS, Wicket, Struts, plain servlets, etc. In well designed application servers the unability to reach web tier classes from the EJB tier on is already enforced by (Java EE default) restrictions in classloaders.
Keep the EJB free of JSF dependencies. Perform the desired job in an eagerly initialized application scoped JSF managed bean instead.
#ManagedBean(eager=true)
#ApplicationScoped
public class App {
private List<SelectItem> someItems;
#EJB
private AppService service;
#PostConstruct
public void init() {
// Populate your List<SelectItem> here.
}
}

Related

What is the search scope of CDI in case of injectable bean lookup?

I have a multi module maven project (a Java EE app with ear, persistence, web, ejb, api, bl and other modules), where I'd like to use Weld CDI.
When I try to inject a bean, where will Weld search for injectable beans? Will Weld search in all the modules, where a beans.xml is placed to WEB-INF or META-INF regardless from their dependencies (or dependencies matter somehow?), or will Weld be able to inject a bean from an other deployment? I tried to find a document, which describes the mechanism and boundaries of bean lookup, but I haven't found anything yet.
What you're describing is part of the overall EE spec, not the CDI spec. but yes, in general the contents of your EAR will be discovered as distinct applications (per the EE spec). This means that you may not be able to access individual beans across JARs. It is highly recommended to use WAR deployment with CDI.

Guice Deployment exception

In Airpal used Guice for DI framework, in my project we are using glassfish 4.1 payara server RESTful web services, Jersey version 2.21.
issue 1: if use Guice got some runtime exceptions
Error occurred during deployment: Exception while loading the app : CDI deployment failure:WELD-001409: Ambiguous dependencies for type Validator with qualifiers #Default at injection point [UnbackedAnnotatedField] #Inject private org.hibernate.validator.internal.cdi.interceptor.ValidationInterceptor.validator at org.hibernate.validator.internal.cdi.interceptor.ValidationInterceptor.validator(ValidationInterceptor.java:0) Possible dependencies: - org.apache.bval.cdi.ValidatorBean#33aeb01, - ValidatorBean [id=org.hibernate.validator.internal.cdi.ValidatorBean_default] . Please see server.log for more details.
issue2: if didn't use Guice how can bind airlift client in jersey 2.21 RESTful.
Please help me. anybody know this issue who are using Airpal+presto+glassfish4.1+jersey2.21+maven3.0
It seems that since both Guice and standard Java EE CDI use the same #Inject annotations, the CDI mechanism is triggered but fails to find dependencies, because your applcation is configured with Guice.
The simplest solution with GlassFish/Payara is to disable implicit CDI when deploying the application (there is a checkbox in Admin console when deploying, or an option to asadmin command).
You can disable CDI in the application archive in a XML descriptor too. Have a look at Payara Server docs about disabling CDI or filtering CDI scanning. Note that most options are available only in Payara Server and not in GlassFish 4.1.
The CDI is triggered either by
- putting beans.xml into you application (I don't expect you put it there, because you're using Guice, but check if it wasn't generated by your IDE for some reason)
- annotating one or more classes with annotations that trigger CDI - e.g. any EJB annotation (#Stateless, #Stateful,...)

CDI interceptor injected into a jersey RS service(resource) not working?

So, I have a tomcat 8 + jersey 2.5.1 + weld CDI app that works very well in most cases. Where it fails is that I am unable to intercept jersey resource method calls with a CDI interceptor. This makes sense because a jersey resource class is not a CDI bean. Then, is there any way to make a CDI interceptor work in jersey? Another way to ask this question: Can a CDI bean be used as a Jersey resource?
Thanks!
EDIT:
Before I wrote my RESTful resources using Jersey, I had CDI interceptors that were used to begin and commit database transactions. I really need to follow the same or similar pattern to implement this cross-cutting transaction injection in my RESTful jersey resources. That is the main reason for asking this question.
Thanks again!
Can a CDI bean be used as a Jersey resource?
Yes, but since Jersey's DI is based on hk2 and not CDI, you need a bridge.
In glassfish such a bridge is realized by the module jersey-gf-cdi:
<dependency>
<groupId>org.glassfish.jersey.containers.glassfish</groupId>
<artifactId>jersey-gf-cdi</artifactId>
<version>2.6</version>
</dependency>
The module registers itself automatically and works on Tomcat beautifully (assuming you have correctly bootstrapped both Jersey and Weld).
Unfortunately, the versions before 2.6 relies on JNDI only, searching the provider under 'java:comp/BeanManager' which Tomcat does not allow.
A fix for this behaviour is available for 2.6 (a pull request I made some time ago), and falls back on CDI.current().getBeanManager().
I tested it on Tomcat 7 and works correctly, should work on Tomcat 8 too.
Adam Bien in one presentation recommends that you separate your Service (CDI or EJB) class from your RESTful resources class. His reason was that the RESTful class usually uses the HttpHeaders injected by Jersey yet not available in the CDI or EJB containers. The hazard is that your RESTful classes could be injected a Null reference of HttpHeaders if any CDI client like the JSF framework uses it.
Thanks to your self-answered question. You have just showed a second use case that validates Adam Bien's recommendation.
Simply keep them apart!

Qi4j in a JSF Application

In Qi4j you have to assemble the composites. Can someone tell me where to handle this in a JSF 2.0 application? Should i extend the FrontController-Servlet ? Or is it enough to assemble at the point, when the application is being deployed and started ?
Thanks a lot!
Using a Qi4j application in a servlet context is quite easy.
Qi4j provide a small library supporting this use case : qi4j-lib-servlet.
All you need is to extends AbstractQi4jServletBootstrap which is a ServletContextListener and register it in your webapp. The only abstract method of this class is from the ApplicationAssembler interface.
Your Qi4j Application will then be assembled and bootstrapped alongside your webapp and the Qi4jServletSupport class provided by the very same project will allow you to get a handle to your Qi4j Application from your code, for example in your managed beans.

Calling #EJB from JSF Managed Bean

We are using JDeveloper 11g.
Both a Model and ViewController project that makes use of ADF fusion and what not.
My web-xml has an EJB reference for a stateful session EJB .
I have a managed bean that's declared in faces-config.
I am trying to access a EJB from inside the managed bean.
I declare
#EJB (name ="LocationServicesEJB")
private LocationServicesEJB locationServices;
When accessing this in a method, the locationServices is null.
I do not see any JNDI type problems in the console,
so I imagine that it's not even bothering to lookup.
Do I need to enable injection or something?
Or do I need to define 'locationServices' as managed property in my faces-config?
Please advise.
Thanx
You are confusing two different types of injection.
There is EJB injection that happens among EJBs by the respective annotation. This type is handled by the EJB container (your application server or OpenEJB e.t.c)
Then there is "normal" injection (ala Spring) that happens between normal Java beans
and is defined in faces-config. This type is handled by JSF.
So decide what you want to do.
My proposal would be to download the official Java EE tutorial and skim through all topics.

Resources