Sunday, 29 June 2014

MTPutty - Multi Tabbed Putty

If you are looking for the option where you can open Putty (free SSH and telnet client) sessions in multiple tabs, you reached to right blog. You can use MTPutty.

MTPutty is free and facilitates wrapping up multiple Putty applications in one tabbed interface. You can save user and password for remote connection to login automatically. This tool also provides facility to configure shell script that you may want to execute after remote server login. I think this is enough detail to know about MTPutty, isn’t it? If not you can refer more detail from here. Now let’s move to setting up and using MTPutty.

Installing and Setting up MTPutty

Before setting up MTPutty ensure to install Putty then only go for MTPutty installation.

Installing and setting up MTPutty in windows environment is quite simple. Download MTputty from here, execute downloaded setup file and provide the installation location. Once installation is done, you can open Mputty UI by executing ‘<mputty-installation-dir>/mtputty.exe’. When you open MTPutty first time you are prompted to provide the Putty executable file location. Once you will provide the Putty executable file location, you can see your Putty connections are imported into MPutty.


Adding New Connection in MTPutty:

To add the new connection in MTPutty, go to ‘Server > Add Server’. You will see below dialog box. Provide the required information like IP, user name, password, display name etc. and click 'OK' button.


You can see the new connection is displayed in left pane in MTputty UI. If you double click on this connection, new tab is opened in right pane and remote server is connected.

Configuring Script to Execute Automatically After Login

Right click on your added connection and click on ‘Script’ tab in opened dialog box. You need to configure two things. Wait period time and the shell script. Note that, shell script will be executed only after configured wait time. If your automatic login is done say in 3000 milliseconds, configure wait  period time around 4000 milliseconds to execute script.


I found this tool is interesting and useful. I hope this will also be useful for you. If you found this post helpful, your comments are most welcome.

Monday, 23 June 2014

Skinny War and Log4j Related Logging Issue

Recently, I packaged my web modules in EAR in skinny war fashion. With this skinny war, I managed to get the size of the EAR down to around 75 MB from 120 MB without skinny war, which is really cool. But this skinny war becomes nightmare, when I started observing log merging issue into different web application's log files at run time. I have noted down the same issue and its possible solutions in this post. If you have applied skinny war in your web modules and you are also the victim of this Log4j logging issue, I am sure you have got the right place to refer. Hope this post will help you out.

Issue: Logs are merged into single log file for different web modules which are packaged in EAR in Skinny War fashion.

I packaged all jars inside EAR/lib (including log4j.jar) so that all WAR refers to jar from this common location not from Web-INF/lib. This way there are no jars in WAR file and it refers to common location. When I deployed this EAR application, it loads the Log4j jar from EAR root (using parent first class loading policy) which is shared across all the wars. I could see application specific log files are created during server start up. But, while accessing application, logs are merged into single log file rather going to application specific log files. Below is the high level overview of EAR structure and Log4j configuration for separate web applications.

EAR Packaging Structure

 |-- META-INF
 |   `-- application.xml
 |-- lib
 |    -- jar1
 |    -- mydao.jar
 |    -- mysevice.jar
 |    -- log4j.jar
 |-- App1-1.0.0.war
 |     -- /WEB-INF/classes/App1-log4j.xml         
 `-- App2-1.0.0.war
 |     -- /WEB-INF/classes/App2-log4j.xml

Web.xml Configuration for different WARs

App1-1.0.0.war: web.xml
<context-param>
            <param-name>log4jExposeWebAppRoot</param-name>
            <param-value>false</param-value>
</context-param>
<context-param>
        <param-name>log4jConfigLocation</param-name>
        <param-value>/WEB-INF/classes/App1-log4j.xml</param-value>
</context-param>
<listener>
        <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>

App2-1.0.0.war: web.xml:                   
<context-param>
   <param-name>log4jExposeWebAppRoot</param-name>
   <param-value>false</param-value>
</context-param>
<context-param>
    <param-name>log4jConfigLocation</param-name>
    <param-value>/WEB-INF/classes/App2-log4j.xml</param-value>
</context-param>
<listener>
      <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>

Solution:

After digging into deep to analyze this issue, I observed Logger.getLogger() returns the logger associated to the web application which is loaded at last. That means, even though I have separate log files created specific to war, but while initializing EAR it overrides logging configuration with log4j.xml of web application which is loaded at last. That is the reason all WAR logs are written in one of the application’s log file.

To overcome this problem, I created custom Repository Selector on top of Log4j’s Repository Selector. With this custom repository selector, you can change the way how the LogManager gets a logger. You can implement this repository selector in a manner such that each context class loader has its own configuration set up with its own log4j.xml file. Using this approach, Logger.getLogger() will return a different logger based on the context class loader. You can refer these links (link1, link2) to get more detail on how you can implement your custom repository selector. With this change, I could see issue is resolved for all the classes which are packaged at web module level but not for all the classes/jars which are packaged at EAR level and shared across the web modules. So till now issue was not resolved fully. 

To resolve it fully, I started searching on net and reached to this link. Then I realized, I should check all the Logger variables in the classes which are packaged in JAR at EAR level. I found, I had below code in my service classes to get the logger instance. This static logger was also the culprit that was causing the log merging issue for the common classes which are shared across the web modules.

public class  MyServiceImpl {

      private static final Logger LOGGER = Logger.getLogger(MyServiceImpl.class);   
      private static final String CLASS_NAME = LOGGER.getName();

      // Other code here
}


I converted all static Loggers to class level instance variables. After making this change, I got log merging issue is resolved for all the classes whether those are at EAR or WAR level. 

Thanks to Repository Selector concept, that helped to solve this log merging issue across different applications. I also raised question on stack overflow for the same issue and posted my findings for other developer's references.