Friday, September 10, 2010

Log4j MDC

Yesterday I happen to see few articles related to Log4j MDC.
I thought of preparing demo for that..
I thought of logging the User in my logs.. Since my application is Spring based.. So the best way is to fetch the user from the Spring Security Context and store that in log4j MDC and use that in log4j.xml.

Log4j MDC:

The MDC class is based on a map. It provides mapped diagnostic contexts. A Mapped Diagnostic Context, or MDC in short, is an instrument for distinguishing interleaved log output from different sources. Log output is typically interleaved when a server handles multiple clients near-simultaneously.

The MDC is managed on a per thread basis. A child thread automatically inherits a copy of the mapped diagnostic context of its parent.

With MDC we can add logging context variables as we pass through the security/filter layer and log as we always would in the business logic.

For example you want to log user name :
1. Create a generic MDCHelper class which will help to set and clear your MDC context.
2. Create a filter and inject your MDCHelper.
3. include your context in Log4j conversion pattern.

Sample:
This class will help to set the Authenticated user in to MDC context, if unauthenticated user then the default value will be set.
public final class MDCUserNameLogHelper {
private static final String USER_NAME = "userName";
private static final String DEFAULT_USER = "system";
public MDCUserNameLogHelper () { }
public static void initLogContext(final String userName) {
if (userName != null) {
MDC.put(USER_NAME, userName); // Stores the userName
} else {
defaultInit(); //if unauthenticated the userName will be null so log default //user.
}
}
public static void clearLogContext() {
MDC.remove(USER_NAME); // clears the user name..
}
static void defaultInit() {
if (MDC.get(USER_NAME) == null) {
MDC.put(USER_NAME, DEFAULT_USER); // Setting the default value if the user is not authenticated.
}
}
}

My filter to fetch the authenticated user :

public class UserNameMDCFilter implements Filter {
private final static Logger logger =
Logger.getLogger(UserNameMDCFilter.class.getName());

public void init(FilterConfig filterConfig) {
}

public void destroy() {
}

public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) {
try
{
final String userName = getUserName();
// Set the MDC context
MDCUserNameLogHelper.initLogContext(userName);

// pass on the request
chain.doFilter(request, response);
}
finally
{
// no matter what happens, clean up
// the variables associated with this Thread/Request
MDCUserNameLogHelper.clearLogContext();
}
}

private String getUserName() {
SecurityContext sc = SecurityContextHolder.getContext();
Authentication a = sc.getAuthentication();
// Here unauthenticated content. So the default user will be logged
if (a == null) {
return null;
}
if (!AnonymousAuthenticationToken.class.isAssignableFrom(a.getClass())) {
Object aPrincipal = a.getPrincipal();
if (aPrincipal instanceof UserDetails) {
UserDetails ud = (UserDetails) aPrincipal;
if (ud == null) {
return null;
}
final String username = ud.getUsername();
log.debug("aPrincipal instanceof UserDetails, username: {}", username);
return username;
} else {
if (aPrincipal instanceof String) {
String ud = (String) aPrincipal;
log.debug("aPrincipal instanceof String, username: {}", ud);
return ud;
}
}
}
}



The above two java classes will be responsible for fetching the Authenticated and Unauthenticated UserName and set and clear that in log4j MDC context.

Changes in Log4j:
Add user MDC context variable on to Conversion pattern.


You can see the userName is appended in your logs :)
there are so many examples in the net. hope it helps you.
Meet you again with some other article.

Reference :
http://ivor.bosloper.nl/2006/11/07/log4j-mdc/

Thursday, September 2, 2010

AOP (Aspect Oriented Programming)

I am using AOP for quite some time.
Yesterday found a nice book and read more about Spring 2.5 and AOP.

Really interesting one.
I will prepare a doc and will update in a while..

Tuesday, April 6, 2010

Financial Messaging Validation Services

I started learning more about financial messaging services and started reading IONA artix and how to use this.
The following article helps me,
I will post my observation in new post..
https://mds.iona.com/validationservice/index.html

Wednesday, March 31, 2010

Oval Validation Framework

I just gone thru the oval validation framewrok and found myself easy and best practice to use this for runtime validation check.

There are lot to explore but my basic tests,
I am personal feeling providing Constraint level check before calling the method is most advantage one..

My sample uses the custom annotation based constraints
For Example,
I want to call the method rank().
There are certain precondition,
Ex: If the subject marks are > 45 then only the rank can be found.
Instead of checking that using if else before calling the rank() or doing that inside rank() is not ok. But the Oval validation really helps in this case.


This is just an example based on Annotation.

Sample :

public void rank(@SubjectPass){
// Some logic goes hear
}

This is how the method definition. Before executing the logic inside the rank() the @SubjectPass will be executed. This one is Custom Annotation based on constraints.

How this works:
You should have some thing like this,

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
@Constraint(checkWith = SubjectPassCheck.class)
public @interface SubjectPass {

}

Then you should have the SubjectPassCheck class.

public class SubjectPassCheck extends AbstractAnnotationCheck
{
public boolean isSatisfied(Object validatedObject, Object valueToValidate, OValContext context, Validator validator)
{
// here your logic..
}
}


This is how the pre oval validation is happening.

There are so many things.
This article is really good. Please have look.

http://oval.sourceforge.net/userguide.html#d4e435

http://jee-bpel-soa.blogspot.com/2008/12/jsr-303-and-oval-validation-framework.html