Sparkles

that were shone when I got tempered!

Posts Tagged ‘apache

Log4j Basics

leave a comment »

Log4j is written java and distributed under Apache Software License.

Althogh it is written in Java it is provided for many other languages such as C, C++, C#, Perl, Python, Ruby, and Eiffel.

There are three main components in log4j.

  1. Loggers : captures the logging information.
  2. Appenders : publishes the logging information to various destinations (File, UNIX-SYS logs, DataBases, Network, Console etc).
  3. Layouts : Formats logging information in different styles.

The latest log4j version can be found at http://logging.apache.org/log4j/ with full-source code, class files, and documentation.

Supportive packages may need to log4j works.

  • Java Mail API: E-mail based logging feature in log4j requires this. This is packaged inside the mail.jar. You can take it from here [https://glassfish.dev.java.net/javaee5/mail/]
  • JavaBeans Activation Framework: The Java Mail API will also require that the JavaBeans Activation Framework. This is packaged inside the activation.jar. You can take it from here [http://java.sun.com/products/javabeans/jaf/index.jsp]
  • Java Message Service: The JMS-compatible features of log4j will require that both JMS and Java Naming and Directory Interface JNDI. You can take it from here [http://java.sun.com/products/jms].
  • XML Parser: JAXP-compatible XML parser is also needed to use log4j. This is packaged inside the Xerces.jar. You can take it from here [http://xerces.apache.org/xerces-j/install.html].

To use log4j, you will need to setup the PATH and CLAASPATH variables properly

	$ pwd /usr/local/apache-log4j-1.2.15
	$ export CLASSPATH=$CLASSPATH:/usr/local/apache-log4j-1.2.15/log4j-1.2.15.jar
	$ export PATH=$PATH:/usr/local/apache-log4j-1.2.15/
	

Architecture
Log4j API follows a Layered Architecture. Layered Architecture’s each layer provides different objects to perform different tasks.

There are two types of objects in log4j framework.

  1. Core Objects
  2. Support Objects

Core Objects

These objects represents the three main components in the Log4j Framework.

  1. Logger Object – (top-level)
  2. Layout Object – (middle-level)
  3. Appender Object – (bottom-level)

Layout Object – (middle-level)

The top-level class in the hierarchy is the abstract class org.apache.log4j.Layout.
This class provides a skeleton implementation of all the common operations across all other Layout objects and declares two abstract methods.

1. public abstract boolean ignoresThrowable()
It indicates whether the logging information handles any java.lang.Throwable object passed to it as a part of the logging event. If the Layout object handles the Throwable object, then the Layout object does not ignore it, and returns false.

2. public abstract String format(LoggingEvent event)
Individual layout subclasses implement this method for layout specific formatting.

Apart from these abstract methods, the Layout class provides concrete implementation for the methods listed below:
1. public String getContentType()
It returns the content type used by the Layout objects. The base class returns text/plain as the default content type.

2. public String getFooter()
It specifies the footer information of the logging message.

3. public String getHeader() –
It specifies the header information of the logging message.

This is Sub-classed as follows giving opportunity to format the logging information in different ways.

  • DateLayout
  • HTMLLayout
  • PatternLayout
  • SimpleLayout
  • XMLLayout

Each subclass can return class-specific information by overriding the concrete implementation of the above described methods.

So, all Layout objects receive a LoggingEvent object from the Appender objects. The Layout objects then retrieve the message argument from the LoggingEvent and apply the appropriate ObjectRenderer to obtain the String representation of the message.
It is also possible to create a Layout object that formats logging data in an application-specific way.

Appender Object – (bottom-level)

There are various Appenders in log4j.

  • AppenderSkeleton
  • AsyncAppender
  • ConsoleAppender
  • DailyRollingFileAppender
  • ExternallyRolledFileAppender
  • FileAppender
  • JDBCAppender
  • JMSAppender
  • LF5Appender
  • NTEventLogAppender
  • NullAppender
  • RollingFileAppender
  • SMTPAppender
  • SocketAppender
  • SocketHubAppender
  • SyslogAppender
  • TelnetAppender
  • WriterAppender

Each Appender object has different properties.

  • layout – Appender uses the Layout objects and the conversion pattern to format the logging information
  • target – The target may be a console, a file, or another item depending on the appender
  • level – This is required to control the filtration of the log messages.
  • threshold – Appender ignores any logging messages that have a level lower than the threshold level.
  • filter – This analyzes the logging information beyond level matching and decide whether logging requests should be handled by a particular Appender or ignored.

Support Objects

Level Objects
Level object defines the granularity and priority of the logging information. There are Seven Levels of logging.

  • OFF
  • DEBUG
  • INFO
  • ERROR
  • WARN
  • FATAL
  • ALL.

Filter Objects
Filter Objects analyzes the logging information and make further decisions on whether it should be logged or not.

An Appender object can have multiple Filter objects associated with it. When a logging information is passed to a particular Appender object, all the Filter objects associated with that Appender need to approve the logging information to be published

ObjectRenderer
The ObjectRenderer object is specialized in providing a String representation for an objects passed to the logging framework. This object is used by the Layout objects to prepare the final logging information.

LogManager
The LogManager object is responsible to manage the logging framework. It reads the initial configuration parameters from a system-wide configuration file or a configuration class and manages the framework

How you can configure the core components using a configuration file.
This involves assigning the Level, defining Appender, and specifying Layout objects in a configuration file.

This configuration file is named as log4j.properties. It keeps the properties in key-value pairs. By default, the LogManager looks for a file named log4j.properties in the CLASSPATH when initialze the logging framework.

Example :

Following is the syntax of log4j.properties file for an appender X:

	# Define the root logger with appender X
	log4j.rootLogger = DEBUG, X

	# Set the appender named X to be a File appender
	log4j.appender.X=org.apache.log4j.FileAppender
	log4j.appender.X.File=${log}/log.out

	# Define the layout for X appender
	log4j.appender.X.layout=org.apache.log4j.PatternLayout
	log4j.appender.X.layout.conversionPattern=%m%n
	

In this example,
The level of the root logger is defined as DEBUG. The DEBUG attaches the appender named X to it.
Set a valid appender(FileAppender) to the appender X. It writes the loggin informaion to a file named log.out located in the log directory (log directory path is given as a System Property like ${variableName}).

You can add the appender to the logger inside the program itself using the below provided method.

	public void addAppender(Appender appender);
	

Set the layout (PatternLayout) for the appender X.

This Pattern Layout is given a specified conversionPattern denoted by the TTCC format.

TTCC

TTCC is a message format used by log4j.[6] TTCC is an acronym for Time Thread Category Component. It uses the following pattern:

  • %r  – Used to output the number of milliseconds elapsed from the construction of the layout until the creation of the logging event.
  • %t  – Used to output the name of the thread that generated the logging event.
  • %p – Used to output the priority of the logging event.
  • %c – Used to output the category of the logging event.
  • %x – Used to output the NDC (nested diagnostic context) associated with the thread that generated the logging event.[7]
  • %X{key} – Used to output the MDC (mapped diagnostic context) associated with the thread that generated the logging event for specified key.[8]
  • %m – Used to output the application supplied message associated with the logging event.
  • %n – Used to output the platform-specific newline character or characters.

Initializing Logger.
The Logger class does not allow us to instantiate a new Logger instance. But it provides number of static methods to obtain a Logger object.

Logging Methods
Once the Logger is instantiated, we can use several methods of the logger to log messages.

  1. public void debug(Object message) – Prints messages with the level Level.DEBUG.
  2. public void error(Object message) – Prints messages with the level Level.ERROR.
  3. public void fatal(Object message) – Prints messages with the level Level.FATAL.
  4. public void info(Object message) – Prints messages with the level Level.INFO.
  5. public void warn(Object message) – Prints messages with the level Level.WARN.
  6. public void trace(Object message) – Prints messages with the level Level.TRACE.

Logging Levels.
Log4j is defined the loggin levels in org.apache.log4j.Level. You can also define your custom levels by sub-classing the Level class. This is described more in above Logger Object.

Level Description

  • OFF – The highest possible rank and is intended to turn off logging.
  • FATAL – Severe errors that cause premature termination. Expect these to be immediately visible on a status console.
  • ERROR – Other runtime errors or unexpected conditions that might still allow the application to continue running. Expect these to be immediately visible on a status console.
  • WARN – Use of deprecated APIs, poor use of API, ‘almost’ errors, potentially harmful situations, other runtime situations that are undesirable or unexpected, but not necessarily “wrong”. Expect these to be immediately visible on a status console.
  • INFO – Interesting runtime events (startup/shutdown). Expect these to be immediately visible on a console, so be conservative and keep to a minimum.
  • DEBUG – Detailed information on the flow through the system. Expect these to be written to logs only.
    TRACE – Most detailed information. Expect these to be written to logs only. Since version 1.2.12.[5]

If the logger level of the request is lRq and
the level of logger is lLgr,
information will be logged only if lLgr >= lRq.

In this case levels are ordered as ALL < DEBUG < INFO < WARN < ERROR < FATAL < OFF.


Reference : 

Written by Namal Fernando

April 14, 2015 at 9:59 am

Posted in Java, log4j

Tagged with , ,

Demo REST project with Camel CXF

leave a comment »

1. Create a .war project (java 1.7 or above) using Maven as follows.

Here we are using the eclipse as the IDE and the Maven. The prefered java version is 1.7 or greater.

1-create_maven_war_prj

2. This is the folder structure of it once it is created.

2-folderStructure

3. Include the necessary dependencies to the pom.xml file as follows.

Here, we’re mainly include the Apache Camel (including camel cxf jars), Apache Common IO and SLF4j jars. Camel is using Common IO internally so it must be also used. And spring jars are also used in here. Springs are used to load the ApplicationContexts automatically.


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>demo.restapi</groupId>
<artifactId>demo.restapi</artifactId>
<version>1.0.0</version>
<packaging>war</packaging>
<name>Rest API demo project</name>
<description>Rest API demo project</description>

<properties>
<camel-web>2.5.0</camel-web>
<camel-version>2.12.0</camel-version>
<xbean-spring-version>3.5</xbean-spring-version>
</properties>

<dependencies>

<!-- Spring + Camel jars -->

<dependency>
<groupId>org.apache.xbean</groupId>
<artifactId>xbean-spring</artifactId>
<version>${xbean-spring-version}</version>
</dependency>

<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring</artifactId>
<version>${camel-version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jms</artifactId>
<version>${camel-version}</version>
</dependency>

<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-stream</artifactId>
<version>${camel-version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>

<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-cxf</artifactId>
<version>${camel-version}</version>
</dependency>

<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-cxf-transport</artifactId>
<version>${camel-version}</version>
</dependency>

<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>2.7.6</version>
</dependency>

<!-- Other jars (logging, io etc) -->

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.5</version>
</dependency>

</dependencies>

</project>

4. Add the below configurations to the WEB-INF/web.xml

Here, we are adding the applicationContext.xml as the contextConfigLocation and the listener classes. Package of the  all routers implementation classes must be mentioned in the applicationContext.xml.


<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:web="http://xmlns.jcp.org/xml/ns/javaee"
 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
 <context-param>
 <param-name>test</param-name>
 <param-value>true</param-value>
 </context-param>
 <context-param>
 <param-name>contextConfigLocation</param-name>
 <param-value>/WEB-INF/applicationContext.xml</param-value>
 </context-param>
 <listener>
 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>
</web-app>

5. Add the below configurations to the WEB-INF/applicationContext.xml.

The package containing all the routes must be specified in the camelContext/camel:package tag. Here in our demo project, the router is mentioned in the camel.route package.


<?xml version="1.0" encoding="UTF-8"?>
<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor
 license agreements. See the NOTICE file distributed with this work for additional
 information regarding copyright ownership. The ASF licenses this file to
 You under the Apache License, Version 2.0 (the "License"); you may not use
 this file except in compliance with the License. You may obtain a copy of
 the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required
 by applicable law or agreed to in writing, software distributed under the
 License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
 OF ANY KIND, either express or implied. See the License for the specific
 language governing permissions and limitations under the License. -->

<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
 xmlns:camel="http://camel.apache.org/schema/spring" xmlns:p="http://www.springframework.org/schema/p"
 xsi:schemaLocation="
 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
 http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
 ">

<bean id="contextApplicationContextProvider" class="conf.ApplicationCtxProvider"></bean>

 <camelContext xmlns="http://camel.apache.org/schema/spring"
 id="Demo-Camel">

 <!-- All the Routes should be created within below Package -->
 <camel:package>camel.route</camel:package>

 </camelContext>

</beans>

6. Add the ApplicationContext classes

These classes are loaded during the Spring-Initialization.

a. ApplicationCtxProvider

This class which implements ApplicationContextAware, is automatically loaded during Spring-Initialization.


package conf;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class ApplicationCtxProvider implements ApplicationContextAware {

@Override
public void setApplicationContext(ApplicationContext ctx)
throws BeansException {
ApplicationCtx.setApplicationContext(ctx);
}
}

b.ApplicationCtx.

This is injected from the class “ApplicationCtxProvider” which is automatically loaded during Spring-Initialization. This get access to the Spring ApplicationContext from everywhere in your Application.


package conf;

import org.springframework.context.ApplicationContext;

public class ApplicationCtx {

private static ApplicationContext ctx;

// Injected from the class "ApplicationCtxProvider" which is automatically loaded during Spring-Initialization.

public static void setApplicationContext(
ApplicationContext applicationContext) {
ctx = applicationContext;
}

// Get access to the Spring ApplicationContext from everywhere in your Application.

public static ApplicationContext getApplicationContext() {
return ctx;
}
}

7. Implement the Camel router (DemoRouteBuilder).

This class is the router that takes all the REST calls to our REST service. To be run automatically, this must be included in the camel.route as it is mentioned in the aplicationContext.xml. So, it will run automatically start to run when the server is starting. Here we are mentioning the cxfrs URI that will be considered as the Endpoint URI. Here we should specify the resourceClasses to point the request to the implementation. Here,  http://localhost:9003/rest is considered as the root URI for the REST service. Rest of the path will be defined in the resource classes. Here, MappingProcessor implements the Camel Process


package camel.route;

import org.apache.camel.builder.RouteBuilder;

import camel.process.MappingProcessor;
import rs.DemoRequestServiceImpl;

public class DemoRouteBuilder extends RouteBuilder {

private static final String REST_ENDPOINT_URI = "cxfrs://http://localhost:9003/rest?resourceClasses=rs.DemoRequestServiceImpl";

@Override
public void configure() {
errorHandler(noErrorHandler());

from(REST_ENDPOINT_URI)
.routeId("RestFulService")
.process(new MappingProcessor(new DemoRequestServiceImpl()));
}

}

8. Implement the Camel Processes (MappingProcessor).

Here, MappingProcessor implements the Camel Process. It takes the REST Impl instance and uses the reflection in the process method for it’s implementation as below.


package camel.process;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.component.cxf.common.message.CxfConstants;
public class MappingProcessor implements Processor {

private Class<?> beanClass;
private Object instance;

public MappingProcessor(Object obj) {
beanClass = obj.getClass();
instance = obj;
}

@Override
public void process(Exchange exchange) throws Exception {
String operationName = exchange.getIn().getHeader(CxfConstants.OPERATION_NAME, String.class);
Method method = findMethod(operationName,exchange.getIn().getBody(Object[].class));
try {
Object response = method.invoke(instance, exchange.getIn().getBody(Object[].class));
exchange.getOut().setBody(response);
} catch (InvocationTargetException e) {
throw (Exception) e.getCause();
}
}

private Method findMethod(String operationName, Object[] parameters)throws SecurityException, NoSuchMethodException {
return beanClass.getMethod(operationName,getParameterTypes(parameters));
}

private Class<?>[] getParameterTypes(Object[] parameters) {
if (parameters == null) {
return new Class[0];
}
Class<?>[] answer = new Class[parameters.length];
int i = 0;
for (Object object : parameters) {
answer[i] = object.getClass();
i++;
}
return answer;
}

}

9. Creating the Rest IMPL classes.

Here, this is the main IMPL classes of the REST implementation. Here the paths are defined by using the @Path annotation. Here, the main path is defined as the /hotelservice. So, each method defined in this class must be called starting from http://localhost:9003/rest/hotelservice. Each implementation methods is defined with dedicated paths.

Here,  getAvailabilityResults(Long id) will be called as http://localhost:9003/rest/hotelservice./hotels/10. Here this methods takes the Long path parameter as 10. And it will be forwarded to the concrete implementation in DemoRequestServiceImpl.java class. Here, getAvailabilityResults is defined as a GET method and getSearhResults(String request) as a POST methos.

a. IDemoRequestService.java

package rs;

import javax.jws.WebParam;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

@Path("/hotelService")
@Consumes("application/json")
@Produces(MediaType.APPLICATION_JSON)
public interface IDemoRequestService {

 @GET
 @Path("/hotels/{id}")
 @Produces(MediaType.APPLICATION_JSON)
 Response getAvailabilityResults(@PathParam("id") Long id); 

 @POST
 @Path("/search")
 @Produces(MediaType.APPLICATION_JSON)
 String getSearhResults(@WebParam(name="request") String request); 

}

b. DemoRequestServiceImpl.java

package rs;

import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DemoRequestServiceImpl implements IDemoRequestService {

 final Logger logger = LoggerFactory.getLogger(DemoRequestServiceImpl.class);

 @Override
 public String getSearhResults(String request) {

 logger.info("getSearhResults().request : " + request);

 return "Hello request " + request;
 }

 @Override
 public Response getAvailabilityResults(Long id){

 logger.info("getSearhResults().Long : " + id);
 return Response.ok("Hello request ID :"+id).status(Status.OK).build();
 }

}

9. Final Folder structure.

3-final-folder-structure

10. Build the project by running the pom.xml through Maven.

Here, I have used clean install package as the maven goal. I executed the maven goals within the eclipse.

11. Deploy the demo.restapi-1.0.0.war in a web container like tomcat.

Here, I used the tomcat8 to deploy the REST service. When tomcat is starting, router is deployed automatically. Then the specified requests (GET ot POST) we are sent to the END POINT URI will be taken to process by the router.

12. Test the GET method.

Here, we can test the GET method using the browser as follows

Hit http://localhost:9003/rest/hotelService/hotels/17 in the browser and get the response as “Hello request ID :17”

13. Test the POST method

– Await !!!

Written by Namal Fernando

June 29, 2014 at 5:18 pm

Ruth's Reflections

Contemplations from quakey quirky Christchurch

TED Blog

The TED Blog shares interesting news about TED, TED Talks video, the TED Prize and more.

Ziplok

Learn and discover simple things

Meihta Dwiguna Saputra's Knowledge Base

~In learning you will teach and in teaching you will (re)learn~

The Java Blog

Thoughts, tips and tricks about the Java programming language

Sparkles

that were shone when I got tempered!