Showing posts with label log4j. Show all posts
Showing posts with label log4j. Show all posts

Saturday, December 12, 2009

OSGi -Spring - Configuration Admin - Dynamic Property file changes

Normally we have been reading the property files ourselves or used spring property-holder feature or even cm-properties. In all these cases update to the property file are not visible.

You can now use the managed-properties under Configuration Admin and have the values updated in your bean automatically whenever you change the property file. You just drop a property file inside pickup directory and under the bean definition specify the persistent-id as follows:


// Have a property file with name myPropertyFile
<osgix:cm-properties id="config" persistent-id="myPropertyFile"/>

//declare a property place holder config with id of osgi:cm
<context:property-placeholder properties-ref="config"/>

//bean definition using teh property file
<bean id="configTest" class="com.test.ConfigTest">
<osgix:managed-properties persistent-id="myPropertyFile" update-strategy="container-managed" /> <property name="propertyValue" value="${propertyValue}"></property>
</bean>

Now first add the property file to the pick up folder and start the DM server. The setPropertyValue() setter will be called and the value will be initialized when application bundle is dropped.

[There are multiple calls to this setter because of the osgi configuration admin]

Now when the property file in changed in the pickup directory , the setter method will be called and new value will be set into the bean.

Incase you want to manage the updates yourself you can change the update-strategy and provide the update-method in the bean. In this case all the key/values are provided to the method in form of a Map.

<bean id="configTest" class="com.test.ConfigTest">
<osgix:managed-properties persistent-id="myPropertyFile"
update-strategy="bean-managed" update-method="refresh" />
<property name="propertyValue" value="${propertyValue}"></property>
</bean>

The ConfigTest class is as follows

public class ConfigTest {

private int propertyValue;

public void setPropertyValue(int propertyValue) {

System.out.println("setter called for property"+propertyValue);
this.propertyValue = propertyValue;
}


public void refresh(Map <String,String> keyVals)
{
System.out.println("referhs called with value"+keyVals);
}

}

PS:

Do not share the same persistent-id (PID) between multiple bundles or definitions, as only one of them will receive notifications. managed-properties relies on org.osgi.service.cm.ManagedService contract which mandates that each ManagedService instance must be identified with its own unique PID.

Hence the best option in a service model is to have a configuration service reading the property file and giving notifications to required bundles.

Sunday, November 15, 2009

Configuring Component based logging in OSGi using Log4j

Initialize reading of the log4j xml in any of the core bundles. Ensure that this bundle doesnt get bounced often.Configure the values to include log4j xml and reload delay.The init method can look something similar to the one below.

public void initialize() {
try {
try {
String logConfig = "D://temp//poc_log_config.xml";
long configReloadDelay = (long) (1 * 30 * 1000);
if (logConfig != null && (new java.io.File(logConfig).exists())) {
if (logConfig.endsWith("xml")) {
org.apache.log4j.xml.DOMConfigurator.configureAndWatch(
logConfig, configReloadDelay);
} else {
org.apache.log4j.PropertyConfigurator
.configureAndWatch(logConfig, configReloadDelay);
}
} else {
org.apache.log4j.BasicConfigurator.configure();
}
} catch (Exception initErr) {
initErr.printStackTrace();
}
} catch (Exception err) {
}

}


The log4j xml will look as follows

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

<appender name="PRODUCT1" class="com.test.anyappender">
<param name="File" value="D:\\temp\\product1\\product1log.log"/>
<param name="MaxFileSize" value="100000000"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{HH:mm:ss,SSS} - %m%n"/>
</layout>
<param name="Threshold" value="DEBUG"/>
</appender>

<appender name="PRODUCT2" class="com.test.anyAppender">
<param name="File" value="D:\\temp\\product2\\product2.log"/>
<param name="MaxFileSize" value="100000000"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{HH:mm:ss,SSS} - %m%n"/>
</layout>
<param name="Threshold" value="DEBUG"/>
</appender>

<root>
<level value="OFF" />
</root>

<logger name="test1">
<appender-ref ref="PRODUCT1"/>
<level value="INFO" />
</logger>

<logger name="test2">
<appender-ref ref="PRODUCT2"/>
<level value="DEBUG" />
</logger>

</log4j:configuration>


Now in any bundle code you can access any component logger as follows

static final Logger TEST_LOGGER = Logger.getLogger("test1");

use TEST_LOGGER.debug("any debug message");

By the above approach we can just have a single log4j bundle in the repository and not only avoid issues occuring from static variables but also can take full benefit of log4j API's.

Thursday, March 5, 2009

Log4j Slf4j issues in Spring Dm

If you try to use log4j in any application under Spring DM we may get some ClassNotFound exceptions . The issue could be the following

com.springsource.slf4j.org.apache.log4j-1.5.6.jar - is present in

springsource-dm-server-ee-1.0.2.RELEASE\repository\bundles\ext directory and it shares a package org.apache.log4j

Now when you put your log4j jar into repository\bundles\usr - it also shares the same package
org.apache.log4j .

Hence one in the repository is resolved first . So all requests to classes in the log4j jar within package org/apache/log4j will give ClassNotFound Exceptions as it looks for these classes in slf4j jar .

The easiest way i resolved this was by deleting com.springsource.slf4j.org.apache.log4j-1.5.6.ja from the repository . This change did not affect any logging of the spring Dm server.

Another way to solve this is

Import-Package: org.apache.log4j;bundle-symbolic-name="com.springsource.org.apache.log4j"

http://forum.springsource.org/showthread.php?t=73354

Log4j/Struts Behaviour in OSGi

Log4j/Struts behaves weird if the these jar are put under repository, because this single static instance inside these jars are shared by all other bundles.

Example: Struts(struts properties),log4j(log4/properties)

All the properties are written into static members.Since the single instance is shared by both the bundles applications, the value of static references will be overridden and both the application will use the same settings.

This case is not specific to spring Dm , it will also occur when common configuration object
is put under common lib in tomcat.

Example: log4j/struts jar in tomcat common lib

Friday, August 1, 2008

Simplest way to Configure Logging using Log4j

Ensure the log4j.jar & log4j.properties are in the classpath

Add the following into the required classes where logging is needed , so that log shows file name for each logger statement .

private static org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger([classname].class);

folowed by logger.[info,debug,error,fatal etc]("logger message");

Contents in Log 4j.properties

log4j.rootLogger=ON, ROOT[enabling the root logger]
log4j.appender.ROOT=org.apache.log4j.DailyRollingFileAppender[saving logs on the daily basis with date appended]
log4j.appender.ROOT.File=/a/b/c.log[root log file path]
log4j.appender.ROOT.layout=org.apache.log4j.PatternLayout
log4j.appender.ROOT.layout.ConversionPattern=%d{dd MMM yyyy HH:mm:ss } %-5p [%t] %c{2} - %m%n [pattern for display in each line]

#FILE APPENDER [another logger file ]
log4j.appender.F2=org.apache.log4j.DailyRollingFileAppender
log4j.appender.F2.File=/a/b/d.log
log4j.appender.F2.layout=org.apache.log4j.PatternLayout
log4j.appender.F2.layout.ConversionPattern=%d{dd MMM yyyy HH:mm:ss } %-5p [%t] %c{2} - %m%n


log4j.logger.org.apache=ERROR[apache specific errors to be shown on both logger files]
log4j.logger.com.example=DEBUG,F2[for com.example modules debug status messages to be shown in second logger file]

For Log4j debugging
Append -Dlog4j.debug in JAVA_OPTS in catalina.sh which will enable detailed logs in catalina.out showing the logger configerations.

Wednesday, July 23, 2008

Adding Logger interceptor in Struts

When i had a requirement to add user name and session id to every logger statement for debugging purposes i did not think it would be so easy. I came across sites which suggested adding some extra modules and configurations into the log4j.

But i realized there was a much simpler way which was to modify the thread name appending application specific user name and session id into it. As anyways log4j will print the thread name at every logger statement . Thus with minimal changes my cause was served. I added this functionality into every request by making it as a interceptor and adding it into the basic stack.
I have attached the interceptor code for reference.

Tasks get easy when seen for different perspectives.

 
Free Domain Names @ .co.nr!