Logback and Jboss 7 - don't work together? - jboss7.x

I am having a curious problem. I had this Java application which was previously deployed in tomcat and happily used logback classic as an slf4j implementation. Now when we tried to deploy the same app in a jboss 7.1.final server it doesn't even deploy the application maoning about
java.lang.ClassCastException: org.slf4j.impl.Slf4jLoggerFactory cannot be cast to ch.qos.logback.classic.LoggerContext
This is the offending line of code
final LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
The class that has his is spring injected and that is failing - hence the whole application cannot be deployed. Anyone got a solution to this? Thanks in advance
After looking in this site plus other forums I realised that Jboss 7 comes bundled with it's own slf4j implementation and implement the same ILoggerFactory interface that LoggerContext in logback does. Our application tried to get an instance of the same but the app server imposes it's own slf4j implementation.
I tried to modify the module.xml in jboss\modules\org\slf4j\impl\main and pointed it to logback jars.
<resources>
<resource-root path="logback-classic-0.9.28.jar"/>
<resource-root path="logback-core-0.9.28.jar"/>
</resources>
Now when I start the application I am getting a serious error
Exception starting filter WicketFilter: java.lang.ClassCastException: ch.qos.logback.classic.LoggerContext cannot be cast to ch.qos.logback.classic.LoggerContext
I am at my wits end. Any jboss and logback experts can help?
Thanks in advance

You need to exclude the servers version of slf4j from your deployment. Create a jboss-deployment-structure.xml file and place it in either your WARS META-INF or WEB-INF directory.
The contents of the file should look like this:
<jboss-deployment-structure>
<deployment>
<!-- Exclusions allow you to prevent the server from automatically adding some dependencies -->
<exclusions>
<module name="org.slf4j" />
<module name="org.slf4j.impl" />
</exclusions>
</deployment>
</jboss-deployment-structure>

If you are using the bridges for jul or jcl in your app, you should exclude them too:
<module name="org.slf4j" />
<module name="org.slf4j.jcl-over-slf4j" />
<module name="org.slf4j.impl" />
<module name="org.jboss.logging.jul-to-slf4j-stub" />

There is alternative approach:
you got logging configured in your war
you got all dependencies in your war
you don't configure anything in JBoss server directory, not even additional JBoss modules
Just disable JBoss logging completely and rely on the dependencies in your war. Edit your jboss-deployment-structure.xml as follows:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
<deployment>
<exclusions>
<module name="org.apache.commons.logging" />
<module name="org.apache.log4j" />
<module name="org.jboss.logging" />
<module name="org.jboss.logging.jul-to-slf4j-stub" />
<module name="org.jboss.logmanager" />
<module name="org.jboss.logmanager.log4j" />
<module name="org.slf4j" />
<module name="org.slf4j.impl" />
<module name="org.slf4j.jcl-over-slf4j" />
</exclusions>
</deployment>
</jboss-deployment-structure>
Once you deploy your app, bootstrap logging (boot.log) keeps working also server.log will show deployment logging. But all your application is logged through your (in this example) slf4j+logback in your war.
Note that you should not need to run JBoss with -Dorg.jboss.logging.provider=slf4j, if you specify this, you will need to provide JBoss modules (typically slf4j-api, logback-classic and logback-core), but it is not worth the effort, as JBoss logging is now used only for bootstrap (boot.log) and for deployment info (server.log).
References:
http://tinyapps.blogspot.com/2013/01/getting-logback-and-slf4j-to-work-in.html
https://stackoverflow.com/a/19695680/2587343

To make independent logging with Logback + Json in JBoss EAP 7.0 I need to exclude outdated Jackson implementation too:
jboss-deployment-structure.xml
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
<deployment>
<!-- https://docs.jboss.org/author/display/AS7/Class%20Loading%20in%20AS7.html -->
<!-- https://docs.wildfly.org/16/Developer_Guide.html -->
<exclusions>
<!-- Rely on WAR's SLF4j + Logback instead of JBoss logmananger. -->
<module name="org.apache.commons.logging" />
<module name="org.apache.log4j" />
<module name="org.jboss.as.logging" />
<module name="org.jboss.logging" />
<module name="org.jboss.logging.jul-to-slf4j-stub" />
<module name="org.jboss.logmanager" />
<module name="org.jboss.log4j.logmanager" />
<module name="org.slf4j" />
<module name="org.slf4j.ext" />
<module name="org.slf4j.impl" />
<module name="org.slf4j.jcl-over-slf4j" />
<!-- Built-in Jackson is without the field: Feature.USE_THREAD_LOCAL_FOR_BUFFER_RECYCLING, need to bundle own version. -->
<!-- https://docs.jboss.org/resteasy/docs/3.0.2.Final/userguide/html/json.html -->
<module name="org.jboss.resteasy.resteasy-jackson-provider"/>
<module name="org.jboss.resteasy.resteasy-jackson2-provider"/>
</exclusions>
</deployment>
</jboss-deployment-structure>
pom.xml
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.9</version>
</dependency>
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>7.0.1</version>
</dependency>
logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<charset>UTF-8</charset>
<pattern>%d{HH:mm:ss.SSS} %5p [%15.15t] %logger %m%ex</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<charset>UTF-8</charset>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %5p [%t] %-40.40logger{39} %m%n%ex</pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${my.log.dir}/test-servlet-logging-%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
<totalSizeCap>500MB</totalSizeCap>
</rollingPolicy>
</appender>
<appender name="JSON-FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${my.log.dir}/test-servlet-logging-%d{yyyy-MM-dd}.ndjson</fileNamePattern>
<maxHistory>30</maxHistory>
<totalSizeCap>500MB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<includeContext>false</includeContext>
<includeMdc>true</includeMdc>
<timestampPattern>uuuu-MM-dd'T'HH:mm:ss.SSSxxx</timestampPattern>
<fieldNames>
<timestamp>#timestamp</timestamp>
<message>message</message>
<thread>thread</thread>
<logger>logger</logger>
<level>level</level>
<levelValue>[ignore]</levelValue>
<version>[ignore]</version>
<stackTrace>ex</stackTrace>
</fieldNames>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
<appender-ref ref="JSON-FILE" />
</root>
</configuration>

Related

Can't register AWS-SDK on Jboss modules correctly

I found the dependency aws-java-sdk was being compiled on a legacy code, having as result a very heavy EAR.
I declared this dependency as provided and wanted to put it as part of the Jboss modules, but no matter where I put it, I'm still having the ClassNotFound issue.
Here is my module.xml:
<module xmlns="urn:jboss:module:1.1" name="com.amazonaws">
<properties>
<property name="jboss.api" value="private"/>
</properties>
<resources>
<resource-root path="aws-java-sdk-1.11.584.jar"/>
</resources>
<dependencies>
<module name="javax.api"/>
<module name="javax.xml.stream.api"/>
<module name="javax.xml.bind.api"/>
<module name="com.fasterxml.jackson"/>
<module name="org.joda.time"/>
</dependencies>
</module>
And the error:
Caused by: java.lang.NoClassDefFoundError: com/amazonaws/auth/AWSCredentials
The problem was on the JAR file, needed sdk-core. Check your JARs always.

Missing jboss.jdbc-driver.org_postgresql_Driver

I'm trying to configure a Postgres datasource in standalone.xml. I've put the driver jar in the right place "jboss-as-7.2.0.Final\modules\org\postgresql\main" and this is my "standalone.xml":
<datasource jta="true" jndi-name="java:jboss/datasources/ProcessEngine" pool-name="ProcessEngine" enabled="true" use-java-context="true" use-ccm="true">
<connection-url>jdbc:postgresql://localhost:5432/camunda_process_engine</connection-url>
<driver-class>org.postgresql.Driver</driver-class>
<driver>postgresql</driver>
<security>
<user-name>postgres</user-name>
<password>postgres</password>
</security>
</datasource>
<drivers>
</driver>
<driver name="postgresql" module="org.postgresql">
<xa-datasource-class>org.postgresql.xa.PGXADataSource</xa-datasource-class>
</driver>
</drivers>
...
"jboss-as-7.2.0.Final\modules\org\postgresql\main\module.xml"
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.0" name="org.postgresql">
<resources>
<resource-root path="postgresql-9.3-1102.jdbc41.jar"/>
</resources>
<dependencies>
<module name="javax.api"/>
<module name="javax.transaction.api"/>
</dependencies>
</module>
I'm trying to start server but it shows errors.
JBAS014775: New missing/unsatisfied dependencies:
service jboss.jdbc-driver.org_postgresql_Driver (missing) dependents: [service jboss.driver-demander.java:jboss/datasources/ProcessEngine, service jboss.data-source.java:jboss/datasources/ProcessEngine]
You also have to add a dependency on your new module to your application. The easiest way to do this is to add a jboss-deployment-structure.xml to the META-INF of your Ear, or if you just have a war, put it in WEB-INF.
<?xml version="1.0"?>
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<deployment>
<dependencies>
<module name="org.postgresql" />
</dependencies>
</deployment>
</jboss-deployment-structure>
When you redeploy, JBoss will know to put your new custom module in the classpath. Decent guide to classloading in AS7 here.

How is possible to exclude all automatic dependencies from being added in JBoss 7?

I want to exclude all automatic dependencies in JBoss 7.
Was not able to find the answer here:
https://docs.jboss.org/author/display/AS7/Class+Loading+in+AS7
Added
Automatic (implicit) dependencies are described here:
https://docs.jboss.org/author/display/AS7/Implicit+module+dependencies+for+deployments
Now I need to do it explicitly. See below.
<jboss-deployment-structure>
<deployment>
<dependencies>
<module name="org.jboss.as.jmx"/>
</dependencies>
<exclusions>
<module name="javaee.api" />
<module name="javax.xml.bind.api" />
<module name="javax.persistence.api" />
...
</exclusions>
</deployment>
</jboss-deployment-structure>
Question if I can do it using simple configuration like:
<jboss-deployment-structure>
<deployment>
<dependencies>
<module name="org.jboss.as.jmx"/>
</dependencies>
<exclusions>
<subsystem name="implicit" />
</exclusions>
</deployment>
</jboss-deployment-structure>
I don't think you can. However, it wouldn't make sense anyway, as for example JDK is part of those implicit dependencies - you really don't want to deploy the entire JDK with your application, now, do you?
Create a set of implicit dependencies that you don't want and put them into jboss-deployment-structure like you have done.

CDI 1.1 with JBoss

Is it possible to use CDI 1.1 with JBoss 7.1.1?
I have a single test war and would like to deploy this war together with weld 2.0.
I disabled the automatically loading of the weld module with the jboss-deployment-structure File:
<jboss-deployment-structure>
<deployment>
<exclusions>
<module name="org.jboss.weld.core" />
</exclusions>
</deployment>
</jboss-deployment-structure>
I also tried to add a extra slot in the jboss/module folder:
<jboss-deployment-structure>
<deployment>
<exclusions>
<module name="org.jboss.weld.core" />
<module name="org.jboss.weld.api" />
<module name="org.jboss.weld.spi" />
</exclusions>
<dependencies>
<module name="org.jboss.weld.core" slot="2.0" />
<module name="org.jboss.weld.api" slot="2.0" />
<module name="org.jboss.weld.spi" slot="2.0" />
</dependencies>
</deployment>
</jboss-deployment-structure>
The deployment failed in both cases because JBoss apparently needs weld for the deployment.
So is it possible to use CDI 1.1 with JBoss 7.1.1 and how?
No, it's not possible. You could try weld-servlet from 2.0 but it won't work with EJB and will get quite confused. The app server integration is different in weld 2.0, so it won't work with AS7.
JBoss Weld community has an installation script to update JBoss AS Weld Subsystem to Weld 2.0;
https://github.com/weld/as7-weld-subsystem . Wildfly is currently in Alpha4 so this may be a better option at this time.

How to determine implemented interfaces for jms connection factories using Spring 3.2.1, Jboss AS7, Aspectj 1.7.1 java 1.7?

We are developing a project in java 1.6 using JBOSS AS7 and we use among others: Aspectj and HornetQ.
We need to upgrade to java 1.7 so we use ASpectj 1.7.1. During the deployment we get the following exception:
Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'eventsJmsTemplate' defined in class path resource [com/company/project/jms/jms.xml]:
Cannot resolve reference to bean 'jmsConnectionFactory' while setting bean property 'connectionFactory'; nested exception is
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'jmsConnectionFactory':
Post-processing of the FactoryBean's object failed;
nestedexception is java.lang.IllegalArgumentException:
warning can't determine implemented interfaces of missing type
com.company.project.aspects.MBeanAttributesAdvice [Xlint:cantFindType]
The mbean is:
<jee:jndi-lookup id="jmsConnectionFactory" jndi-name="java:/JmsXA" />
On other project, We had the same exception when we use a JPA datasource:
<jee:jndi-lookup id="dataSource" jndi-name="java:jboss/datasources/table" />
<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
and we manage to solve the issue by adding on jboss-deployment-structure the module depedency: org.jboss.ironjacamar.jdbcadapters
<jboss-deployment-structure>
<deployment>
<exclusions>
<module name="org.slf4j" />
<module name="org.slf4j.impl" />
<module name="org.apache.log4j" />
</exclusions>
<dependencies>
<module name="org.jboss.ironjacamar.jdbcadapters" />
</dependencies>
</deployment>
</jboss-deployment-structure>
is there any module that we can add in order to pass this exception? or any other way to solve this issue?
I would like to share with you the solution. Add the modules: org.hornetq, org.hornetq.ra , org.jboss.ejb3, org.jboss.ejb-client.
<jboss-deployment-structure>
<deployment>
<!-- Exclusions allow you to prevent the server from automatically adding
some dependencies -->
<exclusions>
<module name="org.slf4j" />
<module name="org.slf4j.impl" />
<module name="org.apache.log4j" />
</exclusions>
<dependencies>
<module name="org.jboss.ironjacamar.jdbcadapters" />
<module name="org.hornetq" />
<module name="org.hornetq.ra" />
<module name="org.jboss.ejb3" />
<module name="org.jboss.ejb-client" />
</dependencies>
</deployment>
</jboss-deployment-structure>
I would like to document what works for me, even if I'm late to this question.
I'm using JBoss 7.1.1 and Spring 3.2.4:
Using, say, annotation based Aspects in your Spring setup will cause the Aspect-Weaver try to go over all components you have, including those you got via JNDI-lookup. The Weaver will stumble over those components, since (I read that somewhere) the Classloader used to load them (JBoss' ModuleClassLoader in my case) will know nothing about my Aspect (living in my project's classloader) and fail with Xlint:cantFindType.
Proxying those components by something within the realm of the project's Classloader solves this problem.
For JDBC datasources:
<jee:jndi-lookup id="dataSource" jndi-name="java:jboss/datasources/myDS" proxy-interface="javax.sql.DataSource" />
For JMS ConnectionFactory
<jee:jndi-lookup id="connectionFactory" jndi-name="java:/JmsXA" proxy-interface="javax.jms.ConnectionFactory"/>
And so on.
This way I do not have to include any extra modules like org.jboss.ironjacamar.jdbcadapters and such.