WELD-000119: Not generating any bean definitions from org.jboss.weld.tests.beanDeployment.noclassdeffound.Bar because of underlying class loading error
Weld reference documentation can be viewed online or downloaded as a PDF.
@ApplicationScoped
and @Singleton
?
Weld assumes requests are single threaded, and uses thread locals to isolate requests. This means that if user created threads are used then built in implementation of the session scope, the request scope and the conversation scope, will become dissociated, and you will find they are no longer active in the new thread, nor able to access their contextual data. The Weld reference guide contains information on how to associate a request to a context and activate it. Doing this in your new thread will cause the contexts to be active, and contain the same contextual data.
The dependent context and the application context will work as usual in any user created thread.
When a Weld-enabled application is deployed on an application server or a web server, proxy classes for beans implementing interfaces or extending classes contained in common libraries are loaded in the class loader (CL) for that library, not the thread context class loader (TCCL). This means that these proxy classes will not be removed from the server when the application is undeployed.
The reason for this approach is to support the use of package scoped classes and members of classes which need to be proxied as beans. Thus the TCCL is not used for the proxy classes generated by Weld.
One way to prevent this problem is to simply deploy those libraries with your application. In this scenario, those classes are loaded in a CL associated with the application and will thus be removed when the application is undeployed.
Weld will not create beans if it can’t load the class, or some class dependency. If that happens, you’ll see a note in the server log.
WELD-000119: Not generating any bean definitions from org.jboss.weld.tests.beanDeployment.noclassdeffound.Bar because of underlying class loading error
You can view more details by increasing the log level of the application server to DEBUG.
Update: Since Weld 2.2 the conversation context is activated lazily and this problem does not occur. If you are using an older version of Weld or need the conversation context to be activated eagerly, read further.
An application may set character encoding of a request by calling the ServletRequest.setCharacterEncoding() method. This method has a limitation: it has to be called before the request parameters or request body are read, otherwise the method call has no effect.
In order to properly activate the conversation context, Weld reads the cid request parameter in the beginning of request processing (see the CDI spec for details). As a side-effect, this makes it impossible to change the character encoding later in the request processing (since request parameters have been read already). As a result, an application servlet or filter that tries to set character encoding will not work since it does that too late.
A workaround is to have the application encoding-setting filter to be called before Weld tries to read the "cid" parameter in the ConversationFilter. This can be done by mapping the custom filter before Weld’s ConversationFilter in web.xml
<web-app 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/web-app_3_0.xsd" version="3.0">
<filter>
<filter-name>SetCharacterEncoding</filter-name>
<filter-class>org.apache.catalina.filters.SetCharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>ignore</param-name>
<param-value>false</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>SetCharacterEncoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CDI Conversation Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
Firstly, this issue only affects CDI 1.1. If possible, go and upgrade to CDI 1.2 (Weld 2.2 or later) where this issue does not occur.
If you cannot do that, read further: This is a known issue in the CDI 1.1 specification and occurs with third-party libraries such as Guava.
A workaround is to configure the application server to require the beans.xml file in bean archives (suppress implicit bean archives). The way to configure this varies across application servers:
GlassFish 4
global configuration:
asadmin set configs.config.server-config.cdi-service.enable-implicit-cdi=false
per-deployment configuration:
asadmin deploy --property implicitCdiEnabled=false <archive>
WildFly 8
global configuration:
/subsystem=weld:write-attribute(name=require-bean-descriptor,value=true)
per-deployment configuration - add the following content to META-INF/jboss-all.xml of the application
<jboss xmlns="urn:jboss:1.0">
<weld xmlns="urn:jboss:weld:1.0" require-bean-descriptor="true"/>
</jboss>
Weld internal classes are not intended to be used in a CDI deployment. As a result, you may encounter validation errors when packaging your application together with Weld in a single fat jar file.
A workaround is to exclude Weld classes from bean scanning:
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
version="1.1" bean-discovery-mode="all">
<scan>
<exclude name="org.jboss.weld.**" />
</scan>
</beans>
The Instance API is often used in loops to obtain multiple instances of a certain bean. Here is an example:
@Inject
private Instance<A> instance;
public void foo() {
// obtain multiple instances of A
for (;;) {
instance.get();
}
By default, each object obtained using Instance remains managed (is not released) until the Instance object is destroyed. This can easily create a memory leak. Therefore, the application should explicitly destroy obtained instances when it no longer needs by calling the Instance.destroy() method.
When things do not work as expected, more information might be helpful in solving the problem. For this reason, you might want to enable the debug (fine) log level for Weld. Each container has its own way to do this:
(more info: Logging Configuration - WildFly)
global configuration - add the following content to the logging subsystem in $JBOSS_HOME/standalone/configuration/standalone-full.xml
<logger category="org.jboss.weld">
<level name="DEBUG"/>
</logger>
per-deployment configuration - add the following line to the logging configuration file (e.g. META-INF/logging.properties) of the application
org.jboss.weld.level=DEBUG
Tip
|
If you want to see the debug messages also in the console, make sure the console handler’s level is set to at least DEBUG. |
(more info: Logging Fraction)
run the uberjar with the following system property:
-Dswarm.logging.loggers.[org.jboss.weld].level=DEBUG
Tip
|
You can also use categories to filter messages - see also Weld Tip 1 - Logging. |
(more info: Setting Log Levels - GlassFish)
global configuration - add the following line to _domain-dir_/config/logging.properties
org.jboss.weld.level=FINE
Tomcat (more info: Logging in Tomcat)
global configuration - add the following line to $CATALINA_HOME/conf/logging.properties
org.jboss.weld.level=FINE
per-deployment configuration - add the following line to WEB-INF/classes/logging.properties
org.jboss.weld.level=FINE
Jetty
For enabling debug logging on Jetty, see Jetty Logging
When running on Tomcat with asynchronous Servlets you may observe the following warnings:
WARN: WELD-000225: Bean store leak was detected during org.jboss.weld.context.http.HttpSessionContextImpl association: org.apache.catalina.connector.Request@5d22c824 WARN: WELD-000335: Conversation context is already active, most likely it was not cleaned up properly during previous request processing: org.apache.catalina.connector.Request@5d22c824 WARN: WELD-000715: HttpContextLifecycle guard not set. The Servlet container is not fully compliant.
A hook exists in the Servlet specification for integrating frameworks such as Weld into a Servlet container.
This hooks is called ServletRequestListener
. The problem here is that Tomcat implements these hooks in a different
way than all the other implementations (Undertow, JBoss Web, Jetty and Grizzly).
Tomcat’s implementation does not allow for an integrating framework that uses ThreadLocals (like Weld does) to be used
correctly in asynchronous Servlet requests. As a result, these warnings are observed as Weld is not able to clean up contexts and
bean instances properly at the end of a request. See the Tomcat bug report
for more details.
Weld versions do not match CDI versioning. An overview is provided in the following table:
Weld version | CDI version | Java version | Java EE version | Description |
---|---|---|---|---|
1.1 |
1.0 |
6+ |
6 |
Not actively developed anymore. Support available with JBoss EAP 6 |
2.1 |
1.1 |
6+ |
7 |
Not actively developed anymore. |
2.2 |
1.2 |
6+ |
7 |
Not actively developed anymore. |
2.3 |
1.2 |
7+ |
7 |
Not actively developed anymore. Support available with JBoss EAP 7.0 |
2.4 |
1.2 |
7+ |
7 |
In maintenance mode. Support available with JBoss EAP 7.1 |
3.0 |
2.0 |
8+ |
8 |
Actively developed and stable version of Weld. |
In Weld 2.1 SLF4J was replaced with JBoss Logging which provides support for the internationalization and localization of log messages and exception messages. However, JBoss Logging itself does not write any log messages. Instead, it only constructs a log message and delegates to one of the supported logging frameworks. And so if you want to enable the debug logging for Weld SE, you’ll have to identify and configure the underlying logging framework.
Which logging framework writes data?
The supported "back-end" frameworks include:
JDK logging
A system property org.jboss.logging.provider
may be used to specify the logging framework directly. Supported values are jboss
, jdk
, log4j
and slf4j
. If this system property is not set, JBoss Logging will attempt to find the logging frameworks from the above-mentioned list on the classpath - the first one found is taken.
Simple way for testing purposes
If you just want to see the debug log messages as quickly as possible try to add org.slf4j:slf4j-simple
on the classpath, set the "back-end" framwork to slf4j
and change the level for org.jboss.weld
, e.g.:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.2</version>
<scope>test</scope>
</dependency>
mvn clean test -Dtest=MyWeldSETest -Dorg.jboss.logging.provider=slf4j -Dorg.slf4j.simpleLogger.log.org.jboss.weld=debug
You should not experience any classloading issues when starting Jetty as an embedded webapp server from within another Java program. However, if you’re using a Jetty standalone instance the deployment with bundled Weld Servlet integration will probably fail and you may observe a similar message in the log:
FAILED org.eclipse.jetty.annotations.ServletContainerInitializerListener@124d02b2: java.lang.NoClassDefFoundError: org/eclipse/jetty/servlet/ServletContextHandler$Decorator java.lang.NoClassDefFoundError: org/eclipse/jetty/servlet/ServletContextHandler$Decorator
The reason is that since Jetty 8 some internal classes are not visible from the web application.
See also Setting Server Classes.
Therefore, we have to tell Jetty not to hide the system classes which Weld integration code is using.
We can use the jetty-web.xml
descriptor (see also Jetty XML Reference):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
<Call name="prependServerClass">
<Arg>-org.eclipse.jetty.util.Decorator</Arg>
</Call>
<Call name="prependServerClass">
<Arg>-org.eclipse.jetty.util.DecoratedObjectFactory</Arg>
</Call>
<Call name="prependServerClass">
<Arg>-org.eclipse.jetty.server.handler.ContextHandler.</Arg>
</Call>
<Call name="prependServerClass">
<Arg>-org.eclipse.jetty.server.handler.ContextHandler</Arg>
</Call>
<Call name="prependServerClass">
<Arg>-org.eclipse.jetty.servlet.ServletContextHandler</Arg>
</Call>
</Configure>
Note that Jetty distributions (from version 9.2.4) contain a dedicated CDI/Weld module which allows to deploy a CDI application without bundling the Weld Servlet integration code. However, note that if you want to deploy application using CDI along with JSF (e.g. weld-numberguess example) you need to copy the following dependencies directly to the CDI module directory:
JSF API
JSF IMPL
Each version of WildFly is shipped with given version of Weld.
However, for every Weld release we also prepare a patch for WildFly which allows you to easily upgrade Weld version.
The patch has a form of .zip
file with name such as wildfly-10.1.0.Final-weld-3.0.0.Beta1-patch.zip
.
The above indicates that the patch is meant for WildFly version 10.1.0.Final and applies Weld in version 3.0.0.Beta1.
Using this patch for other WildFly versions is not guaranteed to work.
Here is an example how to apply the patch for Weld 3.0.0.Beta1 onto WildFly 10.1.0.Final:
Download WildFly (10.1.0.Final) and unzip it to desired location.
Download Weld patch.
Navigate to the WildFly folder.
Run the following command to apply the patch.
$>/{$WILDFLY_FOLDER}/bin/jboss-cli.bat|sh --command="patch apply /path/to/patch/wildfly-10.1.0.Final-weld-3.0.0.Beta1-patch.zip"
You should now see an outcome such as this one.
{
"outcome" : "success",
"result" : {}
}
That’s it! Now you can start your WildFly and try out new Weld.
@ApplicationScoped
and @Singleton
?
Both these contexts behave very similarly. A single bean instance is created and shared across the application. However, there are some important differences.
First of all, @ApplicationScoped
is a normal scope whereas @Singleton
is a pseudo-scope (using the CDI terminology).
What does it mean?
In the first place, for normal scopes a client proxy is always injected.
This is a container construct that delegates all method calls to the current bean instance.
While this may seem as an unnecessary overhead, it allows the container to do the following:
The client proxies are serializable even when the bean itself may not be.
Therefore, you can @Inject
a normal-scoped bean into a bean with a passivating scope (such as @SessionScoped
).
See Weld Reference Guide for more information.
The container initializes the bean instances of normal scoped beans lazily.
In other words, when injecting an @ApplicationScoped
bean a new instance is not created until actually used.
Instead, a shared client proxy is injected.
See Weld Tip 3 - Boost performance of Weld apps for more information.
Client proxies make it possible to support circularities in the bean dependency graph.
There are also some use cases where it’s desirable to destroy/recreate a bean instance via Instance.destroy()
or AlterableContext.destroy()
.
With client proxy in place, all injection points operate on proxy objects that can lookup the contextual instance on demand therefore making it simple and safe to replace the contextual instance for a new one.
On the other hand injecting a direct reference and attempting the same would lead to stale bean instances or working with outdated states of those instances.