Log4j2 in a webapp: MongoCleaner thread creates memory leaks - mongodb

I'm using log4j 2 with a MongoDBAppender in a webapp (servlet spec 2.5).
Here the web.xml:
<listener>
<listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class>
</listener>
<filter>
<filter-name>log4jServletFilter</filter-name>
<filter-class>org.apache.logging.log4j.web.Log4jServletFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>log4jServletFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
<dispatcher>ASYNC</dispatcher><!-- Servlet 3.0 w/ disabled auto-initialization
only; not supported in 2.5 -->
</filter-mapping>
Here the log4j2 configuration:
<Configuration status="warn">
<Properties>
<Property name="MongoDbServer">$${jndi:MongoDB.serverAddress.1.host}:$${jndi:MongoDB.serverAddress.1.port}</Property>
<Property name="MongoDbPassword">$${jndi:MongoDB.password}</Property>
</Properties>
<Appenders>
<NoSql name="databaseAppender">
<MongoDb databaseName="LOGS" collectionName="test"
server="${MongoDbServer}" username="LOGS" password="${MongoDbPassword}" />
</NoSql>
<Async name="Async">
<AppenderRef ref="databaseAppender" />
</Async>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Async" />
</Root>
</Loggers>
</Configuration>
When i undeply the webapp, this error log appears:
SEVERE: A web application appears to have started a thread named [MongoCleaner665622824] but has failed to stop it. This is very likely to create a memory leak.
Any suggestion?
Thanks.

You may have found a bug. Can you raise this in the log4j2 Jira issue tracker?

Make sure to close all instances of com.mongodb.MongoClient. e.g:
MongoClient mongoClient= new MongoClient();
// Do something
mongoClient.close();

Related

Log4J2 : How to Pass Application Name in TCPSocketServer implementation from client to server

I am running a Log4J2 TCPSocketServer on an edge node in a cluster. All the data nodes send log events to the TCPSocketServer on the edge node and also log locally in the data node using the log4j2.xml configuration file as shown below. The Application Name is stored as a System property and is accessible in the data node or client's log4j2.xml configuration using ${sys:ABC.appname}. How can I send the same appname to the edge node where TCPSocketServer is running using the log4j2.xml. I would be using the same Application Name in the log4j2-server.xml to log events into separate log files just like I am doing locally on data node.
Sample snippet from data node or Client - log4j2.xml :
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" >
<Appenders>
<Socket name="socket" host="localhost" port="12345" >
<SerializedLayout />
</Socket>
<File name="MyFile" fileName="/var/log/${sys:ABC.appname}.log" >
<PatternLayout>
<Pattern>%d{ISO8601} %p %c{1.} [%t] %m%n</Pattern>
</PatternLayout>
</File>
</Appenders>
<Loggers>
<Root level="debug">
<AppenderRef ref="socket"/>
<AppenderRef ref="MyFile"/>
</Root>
</Loggers>
</Configuration>
Sample snippet from edge node or Server - log4j2-server.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<File name="MyFile" fileName="/var/log/data/${hostName}-<**This is where I would like to see the appname from data node**>.log" >
<PatternLayout>
<Pattern>%d{ISO8601} %p %c{1.} [%t] %m%n</Pattern>
</PatternLayout>
</File>
<Async name="AsyncFile">
<AppenderRef ref="MyFile" />
</Async>
</Appenders>
<Loggers>
<Root level="WARN">
<AppenderRef ref="AsyncFile"/>
</Root>
</Loggers>
</Configuration>
I used ThreadContext to resolve this issue. Its pretty easy to add Thread Context into the codebase and later use Routing to segregate the log events based on the ThreadContext. I followed the example on this link to do the same https://logging.apache.org/log4j/2.x/faq.html#separate_log_files

JBoss EAP 6.2 and Log4j2 stops writing logs after some time

I am using Log4j2 (RollingFile with routes) in my web application to log application specific logs in a few separate log files. The log4j2.xml file is bundled with in the WAR file.
Log files are generated and logs are generating fine to start with. After some time, it stops writing logs to the existing file and fails creating new folders/files too.
On restart everything resumes working and that is for some time only.
Tried monitoring, couldn't figure out any specific pattern or steps to simulate it.
<Configuration status="error" name="logger">
<Properties>
<Property name="logpath">path_to_log_file</Property>
</Properties>
<Appenders>
<Routing name="RoutingUserLogFile">
<Routes pattern="$${ctx:user}/">
<Route>
<RollingFile name="UserLogFile" fileName="${logpath}/${ctx:user}/MyLogFile.log" filePattern="${logpath}/${ctx:user}/%d{dd-MM-yyyy}-MyLogFile-%i.log.gz">
<PatternLayout>
<Pattern>%d %p %-40C{1.} %m%n</Pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true" />
<SizeBasedTriggeringPolicy size="4 MB" />
</Policies>
</RollingFile>
</Route>
</Routes>
</Routing>
</Appenders>
<Loggers>
<Root>
<level value="debug" />
<AppenderRef ref="RoutingUserLogFile" level="debug" />
</Root>
</Loggers>
</Configuration>

Chainsaw v2 SocketReceiver not working with log4j2 SocketAppender

I'm trying to use Chainsaw v2 from http://people.apache.org/~sdeboy
I don't want to use zero configuration. Just a simple socketAppender/SocketReceiver combo.
I'm using log4j2 with the following configuration
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" >
<Appenders>
<Console name="CONSOLE" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
</Console>
<Socket name="SharathZeroConf" host="localhost" port="4445">
</Socket>
</Appenders>
<Loggers>
<Root level="debug">
<AppenderRef ref="SharathZeroConf" />
<AppenderRef ref="CONSOLE" />
</Root>
</Loggers>
</Configuration>
On ChainSaw, I'm selecting the option "Receive events from network" with port 4445.
However chainsaw doesnt log anything.
I've verified that the appender configuration is correct on log4j side by using the builtin socketserver
java -cp ~/.m2/reposiry/org/apache/logging/log4j/log4j-api/2.0.2/log4j-api-2.0.2.jar org.apache.logging.log4j.core.net.server.TcpSocketServer 4445
So the bug must be on chainsaw side. Any pointers #Scott ?
You're right, I got the same issue. I just tried with LogMX instead, and it works like a charm:
I just had to copy Log4j JARs in LogMX lib/ directory (i.e. log4j-api-2.xx.jar and log4j-core-2.xx.jar)

Spring MVC + Maven + JBoss: can't deploy (The application must supply JDBC connections)

I'm currently trying to setup a Spring MVC 3.1.1 project using Maven and deploying on JBoss 7.1.1.
I have tried a few tutorials but I couldn't finish any as at some point I would get stuck with something that was assumed in the tutorial and nonexistent in my setup.
My second try was to create a "Spring MVC Project" using eclipse and copy/paste the configuration files from a working Spring MVC project to my new one but so far no good.
I created my whole domain using JPA and now that I try to deploy I get this exception: Schema export unsuccessful: java.lang.UnsupportedOperationException: The application must supply JDBC connections.
I found many forum posts etc with people having the same issue but none of the proposed solutions suits my problem. Postgresql driver is well defined in maven dependencies and is in the build path.
Here is the main/src/resources/META-INF/persistence.xml file:
<persistence-unit name="root">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.macoloc.domain.Colocation</class>
<class>com.macoloc.domain.Invitation</class>
<class>com.macoloc.domain.Key</class>
<class>com.macoloc.domain.Message</class>
<class>com.macoloc.domain.MessageSeenBy</class>
<class>com.macoloc.domain.Payment</class>
<class>com.macoloc.domain.PaymentParticipation</class>
<class>com.macoloc.domain.Ping</class>
<class>com.macoloc.domain.Subtask</class>
<class>com.macoloc.domain.Task</class>
<class>com.macoloc.domain.TaskOrder</class>
<class>com.macoloc.domain.User</class>
<class>com.macoloc.domain.Versionable</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="create" />
</properties>
</persistence-unit>
Here is the src/main/webapp/WEB-INF/web.xml file:
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml,/WEB-INF/spring/infrastructure/infrastructure.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
Here is a part of src/main/resources/WEB-INF/spring/appServlet/servlet-context.xml file:
<context:component-scan base-package="com.macoloc" />
<annotation-driven />
<tx:annotation-driven />
<mvc:annotation-driven />
<mvc:resources mapping="/js/**" location="/resources/js/" />
<mvc:resources mapping="/css/**" location="/resources/css/" />
<resources mapping="/resources/**" location="/resources/" />
<beans:bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
And finally the src/main/resources/WEB-INF/spring/infrastructure/infrastructure.xml file:
<context:annotation-config />
<tx:annotation-driven />
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSourceDirect" />
</bean>
<bean id="dataSourceDirect" class="org.postgresql.ds.PGSimpleDataSource">
<property name="user" value="macoloc"></property>
<property name="password" value="macoloc"></property>
<property name="portNumber" value="5432"></property>
<property name="serverName" value="localhost"></property>
<property name="databaseName" value="MaColoc"></property>
</bean>
<bean class="org.springframework.orm.jpa.JpaTransactionManager"
id="transactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
In postgres I've set the user "macoloc" to use DB "MaColoc"'s "macoloc" schema.
Note that the project I'm taking all these configuration files wasn't set by me (obviously since this one is working...). There might be some files unused? I don't know. I'm really new to this.
Any idea where this is going wrong? Do you guys need more files?
Thank you!
EDIT: here's the stacktrace:
16:11:21,568 INFO [org.jboss.as.connector.deployers.jdbc] (MSC service thread 1-8) JBAS010404: Deploying non-JDBC-compliant driver class org.postgresql.Driver (version 9.0)
16:11:21,585 INFO [org.jboss.as.jpa] (MSC service thread 1-4) JBAS011402: Starting Persistence Unit Service 'MaColoc.war#root'
16:11:22,205 ERROR [org.hibernate.tool.hbm2ddl.SchemaExport] (MSC service thread 1-4) HHH000231: Schema export unsuccessful: java.lang.UnsupportedOperationException: The application must supply JDBC connections
at org.hibernate.service.jdbc.connections.internal.UserSuppliedConnectionProviderImpl.getConnection(UserSuppliedConnectionProviderImpl.java:62) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.tool.hbm2ddl.SuppliedConnectionProviderConnectionHelper.prepare(SuppliedConnectionProviderConnectionHelper.java:51) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.tool.hbm2ddl.DatabaseExporter.<init>(DatabaseExporter.java:52) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.tool.hbm2ddl.SchemaExport.execute(SchemaExport.java:368) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.tool.hbm2ddl.SchemaExport.create(SchemaExport.java:305) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.tool.hbm2ddl.SchemaExport.create(SchemaExport.java:294) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:452) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1737) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.ejb.EntityManagerFactoryImpl.<init>(EntityManagerFactoryImpl.java:84) [hibernate-entitymanager-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:904) [hibernate-entitymanager-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:889) [hibernate-entitymanager-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:73) [hibernate-entitymanager-4.0.1.Final.jar:4.0.1.Final]
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl.createContainerEntityManagerFactory(PersistenceUnitServiceImpl.java:162) [jboss-as-jpa-7.1.1.Final.jar:7.1.1.Final]
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl.start(PersistenceUnitServiceImpl.java:85) [jboss-as-jpa-7.1.1.Final.jar:7.1.1.Final]
at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1811)
at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1746)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [rt.jar:1.7.0_21]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [rt.jar:1.7.0_21]
at java.lang.Thread.run(Unknown Source) [rt.jar:1.7.0_21]
And: Most weird, I noticed the tables were created in my DB... What?
You configured JPA to be initialized by Spring (using LocalContainerEntityManagerFactoryBean), but JBoss also sees your persistence.xml and tries to initialize JPA on its own (as required by JPA Specification for application server environments). Obviously, it fails, because you didn't configure a data source in persistence.xml.
To avoid this problem Spring allows you to use different name for persistence.xml:
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
...
<property name = "persistenceXmlLocation"
value = "classpath:/META-INF/spring-persistence.xml" />
</bean>
Alternatively, since Spring 3.1 you can configure JPA without persistence.xml at all.
See also:
LocalContainerEntityManagerFactoryBean
There is a second way to solve this solution. You can tell JBoss to ignore the persistence.xml.
Add the following property to the persistence.xml <properties>
<property name="jboss.as.jpa.managed" value="false"/>
This is explained in the docs as the "jboss.as.jpa.managed - can be set to false to disable container managed JPA access to the persistence unit. The default is true, which enables container managed JPA access to the persistence unit. This is typically set to false for Seam 2.x + Spring applications. "

Bayeux Server Configuration Issue

We had an issue with our CometD/Gigaspaces application creating a duplicate instances of the Bayeux Server. See my previous question posted here.
After investigating this issue with Gigaspaces, it turns out each bean defined in our Application Context File was getting created twice as
GigaSpaces has special treatment for Application Context Files called PU.XML. We've resolved this issue by renaming the PU.XML File but the
problem we have now is that we're not receiving any data on the client side and receive the following error "NetworkError: 400 Unknown Bayeux Transport - http://localhost:9292/cometd".
Previously, when the application created a duplicate instance of the Bayeux Server, we put a workaround in place to terminate the first
instance of the thread that the Bayeux Server was running on and as a result we were able to publish data on our channels using Web Sockets which we configured in the
Application Context File.
Could you have a look at our current configuration and let me know if there is a alternative solution to configure and export the Bayeux Server correctly using Spring? Is it possible the Bayeux bean is not getting exported correctly or if it is getting exported too late??
I've posted our updated Web.XML and Application Context configurations below. The CometD Version/Jars in our POM.XML are the same as my previous post. If you need further info. please let me know.
Current Web.XMl:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>CometDApplication</display-name>
<servlet>
<servlet-name>cometd</servlet-name>
<servlet-class>org.cometd.server.CometdServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>cometd</servlet-name>
<url-pattern>/cometd/*</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- <listener>
<listener-class>org.openspaces.pu.container.jee.context.ProcessingUnitContextLoaderListener</listener-class>
</listener>-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext-gigaspaces.xml</param-value>
</context-param>
</web-app>
Current applicationContext-gigaspaces.XML:
<bean id="Bayeux" class="org.cometd.server.BayeuxServerImpl"
init-method="start" destroy-method="stop">
<property name="options">
<map>
<entry key="logLevel" value="0" />
<entry key="timeout" value="15000" />
</map>
</property>
<property name="transports">
<list>
<!-- The order of the following transports dictates the type of transport
used i.e. Web Sockets then JsonTransport (a.k.a long-polling) -->
<bean id="websocketTransport" class="org.cometd.websocket.server.WebSocketTransport">
<constructor-arg ref="Bayeux" />
</bean>
<bean id="jsonTransport" class="org.cometd.server.transport.JSONTransport">
<constructor-arg ref="Bayeux" />
</bean>
<bean id="jsonpTransport" class="org.cometd.server.transport.JSONPTransport">
<constructor-arg ref="Bayeux" />
</bean>
</list>
</property>
</bean>
<!-- Export the Bayeux Server to the servlet context via springs ServletContextAttributeExporter -->
<bean id="ContextExporter"
class="org.springframework.web.context.support.ServletContextAttributeExporter">
<property name="attributes">
<map>
<entry key="org.cometd.bayeux">
<ref local="Bayeux" />
</entry>
</map>
</property>
</bean>
The code you posted is correct and virtually identical to the test present in CometD, see here and here.
You have something else going on, and debug logs on both client and server will help you understanding.