Thursday, March 27, 2014

Maven respository configuration in settings.xml

The following is an analysis on the maven configuration file settings.xml. In this example, it is assumed that you are working on a computer that is in your company office. So it uses a company proxy to go to the internet. Assume the company name is MyCompany. The maven version in this analysis is 2.2.1.
  1. Maven has its own settings.xml. This is a global file in C:\apache-maven-2.2.1\conf. But the file content is basically all commented out. So it is basically just a placeholder there.
  2. Maven then uses the settings.xml in the user directory C:\Users\userid\.m2
  3. Inside MyCompany network, the http traffic usually uses a proxy.
  4. For IE browser, you can configure the proxy by following the menu: tools --> internet options --> connections - LAN settings. Then you can check "Use Automatic configuration script" and set the URL to the script in the "Address" input field. For example, you can specify the following in the Address: http://autoproxy.MyCompany.com/.
    If the MyCompany proxy is not set, it seems that no traffic can go outside. Even the URL www.google.com will time out. And the central maven repository http://central.maven.org/maven2/ will time out too of course.
  5. For maven, the proxy is configured using the<proxy> tag inside the settings.xml file. For example:
     <proxies>
        <proxy>
           <active/>
           <port>80</port>
           <host>internet.myCompany.com</host>
           <id>my proxy</id>
           <nonProxyHosts>*.myCompany.com</nonProxyHosts>
        </proxy>
     </proxies>
     
  6. Maven uses the Central Repository http://central.maven.org/maven2/ as the default repository. Even if you do not specify any repository in the settings.xml file, maven will use this Central repository.
Because of the license issues, it can be expected that MyCompany needs to have a repository that hold all the permitted java libraries. It will be wrong for the application to be able to download libraries from outside repositories freely, even if it is the central maven repository. So how to achieve this? The trick is in the "mirror" configuration in the settings.xml. There are documents here: https://maven.apache.org/guides/mini/guide-mirror-settings.html. The following are the important things.
  1. By default, Maven will download from the central repository. To override this, you need to specify a mirror.
  2. You can force Maven to use a single repository by having it mirror all repository requests. The repository must contain all of the desired artifacts, or be able to proxy the requests to other repositories. This setting is most useful when using an internal company repository with the Maven Repository Manager to proxy external requests. To achieve this, set mirrorOf to *.
  3. The official Maven 2 repository is at http://repo.maven.apache.org/maven2 hosted in the US.
  4. The ID of the main Maven Central US repository included by default is central.
At MyCompany, the production settings.xml has the following:
   <mirrors>
     <mirror>
          <id>maven.MyCompany.com</id>
          <name>Maven Repository Manager running on maven.MyCompany.com</name>
          <url>http://maven.MyCompany.com/m2</url>
          <mirrorOf>central</mirrorOf>
     </mirror>
   </mirrors>
    
    <repositories>
           <repository>
             <id>mvnown</id>
             <name>Maven Repository Manager running on maven.MyCompany.com</name>
             <url>http://maven.MyCompany.com/m2</url>
           </repository>
     </repositories>
  
From the above, we can see that the maven "central" repository is overridden by the MyCompany repository. The only repository used is http://maven.MyCompany.com/m2. In one project, we got the following error messages when building the application:
Downloading: http://maven.MyCompany.com/m2/org/jboss/jboss-parent/6/jboss-parent-6.pom
[INFO] Unable to find resource 'org.jboss:jboss-parent:pom:6' in repository mvnown (http://maven.MyCompany.com/m2)
Downloading: http://maven.MyCompany.com/m2/org/jboss/jboss-parent/6/jboss-parent-6.pom
[INFO] Unable to find resource 'org.jboss:jboss-parent:pom:6' in repository central (http://repo1.maven.org/maven2)
You can see that maven tried the two repositories: Firstly repository mvnown (http://maven.MyCompany.com/m2). Secondly central (http://repo1.maven.org/maven2).

The first repository is specified in the<repository> setting. The second repository is the default. This error message shows that even if you do not specify the central repository in the settings.xml, maven will still try to download libraries from that repository. In our case, it is mirrored. So what maven got is actually still mvnown (http://maven.MyCompany.com/m2)! And of course, nothing new is found there!

Now if I remove the mirror for the central, what will happen? Can maven find that jboss-parente-6.pom file? You will expect that the answer should be a "Yes". And that is right! It will be found and the build will be a success!

Monday, December 23, 2013

Integrating Spring framework with other web frameworks

When working on using Spring framework in a web application that uses JSF and Facecets, I found the following information from Spring documentation about how to integrate Spring with JSF.

Common Configuration

In web.xml file, declare the following:
<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>

If you don't specify the contextConfigLocation context parameter, the ContextLoaderListener will look for a file called /WEB-INF/applicationContext.xml to load. Once the context files are loaded, Spring creates a WebApplicationContext object based on the bean definitions and stores it in the ServletContext of one's web application.

All Java web frameworks are built on top of the Servlet API, and so one can use the following code snippet to get access to this 'business context' ApplicationContext created by the ContextLoaderListener.

WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(servletContext);

The WebApplicationContextUtils class is for convenience, so you don't have to remember the name of the ServletContext attribute. Its getWebApplicationContext() method will return null if an object doesn't exist under the WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE key. Rather than risk getting NullPointerExceptions in your application, it's better to use the getRequiredWebApplicationContext() method. This method throws an exception when the ApplicationContext is missing.

Once you have a reference to the WebApplicationContext, you can retrieve beans by their name or type. Most developers retrieve beans by name, then cast them to one of their implemented interfaces.

Fortunately, most of the frameworks in this section have simpler ways of looking up beans. Not only do they make it easy to get beans from a Spring container, but they also allow you to use dependency injection on their controllers. Each web framework section has more detail on its specific integration strategies.

Integration with JSF

The easiest way to integrate one's Spring middle-tier with one's JSF web layer is to use the DelegatingVariableResolver class. In faces-config.xml,add the following:
<faces-config>
  <application>
    <variable-resolver>org.springframework.web.jsf.DelegatingVariableResolver</variable-resolver>
      <locale-config>
        <default-locale>en</default-locale>
        <supported-locale>en</supported-locale>
        <supported-locale>es</supported-locale>
      </locale-config>
      <message-bundle>messages</message-bundle>
    </application>
</faces-config>

The DelegatingVariableResolver will first delegate value lookups to the default resolver of the underlying JSF implementation, and then to Spring's 'business context' WebApplicationContext. This allows one to easily inject dependencies into one's JSF-managed beans.

Note that if using Facelets, you need to add the following ViewHandler to the

<application>
  ...
<view-handler>com.sun.facelets.FaceletViewHandler</view-handler>
</application>

Managed beans are defined in one's faces-config.xml file. Find below an example where #{userManager} is a bean that is retrieved from the Spring 'business context'.

<managed-bean>
  <managed-bean-name>userList</managed-bean-name>
 <managed-bean-class>com.whatever.jsf.UserList</managed-bean-class>
  <managed-bean-scope>request</managed-bean-scope>
  <managed-property>
    <property-name>userManager</property-name>
    <value>#{userManager}</value>
  </managed-property>
</managed-bean>

FacesContextUtils

A custom VariableResolver works well when mapping one's properties to beans in faces-config.xml, but at times one may need to grab a bean explicitly. The FacesContextUtils class makes this easy. It is similar to WebApplicationContextUtils, except that it takes a FacesContext parameter rather than a ServletContext parameter.
ApplicationContext ctx = FacesContextUtils.getWebApplicationContext(FacesContext.getCurrentInstance());
The DelegatingVariableResolver is the recommended strategy for integrating JSF and Spring. If one is looking for more robust integration features, one might want take a look at the JSF-Spring project.

References

  1. http://docs.spring.io/spring/docs/2.0.x/reference/webintegration.html

Friday, November 1, 2013

Configure SSL in Weblogic

To test the SSL on weblogic, deploy a web application to the weblogic server. And from the weblogic admin console check the box "SSL Listen Port Enabled" in the "configuration" tab. By default, the SSL listen port on weblogic is 7002. In the following, the web application deployed is assumed to be myapp.

In the startWeblogic.cmd file that starts the weblogic server, you can add the following line that can generate some debug logs:

set JAVA_OPTIONS=%JAVA_OPTIONS% -Dssl.debug=ture -Dweblogic.StdoutDebugEnabled=true -Dweblogic.security.SSL.enforceConstraints=off -Dweblogic.security.SSL.verbose=true 

The Weblogic Default Configuration

By default, Weblogic uses its Demo identity and Demo trust store. More specifically, the following are used:
%WLHOME%\wlserver_10.3\server\lib\DemoIdentity.jks
%WLHOME%\wlserver_10.3\server\lib\DemoTrust.jks
Trust store password: DemoTrustKeyStorePassPhrase
Key store password: DemoIdentityKeyStorePassPhrase
Private key password: DemoIdentityPassPhrase

You can go to the weblogic admin console to look at the configuration. Go to the server and then check the "Keystore" tab and the "SSL" tab.

The following is the test program based on a sample from JSSE tutorial.

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;

import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

/*
 * This example demostrates how to use a SSLSocket as client to
 * send a HTTP request and get response from an HTTPS server.
 * It assumes that the client is not behind a firewall.
 * In this example, one-way SSL is used. The server needs to be trusted.
 */

public class SSLSocketClient {

 public void test() {

  // if you are running this program using jrocket JVM, then the following lines that
  // set the trustStore and trustStorePassword are not needed.
  String trustStore = "C:\\bea1032\\jrockit_160_14_R27.6.5-32\\jre\\lib\\security\\cacerts";
  String trustStorePassword = "changeit";
  System.setProperty("javax.net.ssl.trustStore", trustStore);
  System.setProperty("javax.net.ssl.trustStorePassword",
    trustStorePassword);
    
  System.setProperty("javax.net.debug", "ssl");
  String host = "localhost"; 
  int port = 7002; 
  try {
   SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory
     .getDefault();
   SSLSocket socket = (SSLSocket) factory.createSocket(host, port);

   socket.startHandshake();

   PrintWriter out = new PrintWriter(new BufferedWriter(
     new OutputStreamWriter(socket.getOutputStream())));

   out.println("GET /myapp/ HTTP/1.0");
   out.println();
   out.flush();

   /*
    * Make sure there were no surprises
    */
   if (out.checkError())
    System.out
      .println("SSLSocketClient:  java.io.PrintWriter error");

   /* read response */
   BufferedReader in = new BufferedReader(new InputStreamReader(socket
     .getInputStream()));

   String inputLine;
   while ((inputLine = in.readLine()) != null)
    System.out.println(inputLine);

   in.close();
   out.close();
   socket.close();

  } catch (Exception e) {
   e.printStackTrace();
  }
 }

 public static void main(String[] args) throws Exception {
  SSLSocketClient p = new SSLSocketClient();
  p.test();
 }
}

Note that if you use jrocket as the JVM to run this client program, then you can remove those lines that set the trust store System properties. The jrocket JVM may have added the Weblogic Demo certificate into its trust store.

To Use Custom Identity and Custom Trust

Usually only one-way SSL is used. The client program that talks to the weblogic server will verify the identity certificate of the server to see if it can trust the server. If two-way SSL is enforced, then the client will need to supply its own identity to the weblogic server. More configurations are needed to make this whole thing successful. The following is an example about how to do all the necessary steps. The java keytool utility is used.

On the client side:

  1. Generate identity keystore.
          keytool -genkeypair -keystore myidentity.jks -storepass mytest
          
  2. Export a certificate that authenticates your public key. The following command will generate the file mycert.cer.
          keytool -exportcert -alias mykey -keystore myidentity.jks -storepass mytest -file mycert.cer
          
  3. In this case, we will still use the default jrocket JVM trust store which will trust the Demo certificate from weblogic server.

On the server side:

  1. Create the identity and trust store. In this case, we will still use DemoIdentity. So copy DemoIdentity.jks to C:\DemoIdentity.jks. Also copy DemoTrust.jks to C:\DemoTrust_mycert.jks
  2. Import the client certificate to the trust keystore so the server will trust the client.
        keytool -import -alias mykey  -file mycert.cer -keystore DemoTrust_mycert.jks 
        -storepass DemoTrustKeyStorePassPhrase 

On Weblogic admin console "KeyStores" tab.
For the "KeyStores", choose "Custom Identity and Custom Trust" from the drop-down list. And fill out the following.
--Identity--
Custom Identity Keystore: C:\DemoIdentity.jks
Custom Identity Keystore Type: JKS
Custom Identity Keystore Passphrase: DemoIdentityKeyStorePassPhrase
Confirm Custom Identity Keystore Passphrase: DemoIdentityKeyStorePassPhrase

--Trust--
Custom Trust Keystore: C:\DemoTrust_mycert.jks
Custom Trust Keystore: JKS
Custom Trust Keystore Passphrase: DemoTrustKeyStorePassPhrase
Confirm Trust Keystore Passphrase: DemoTrustKeyStorePassPhrase

On Weblogic admin console "SSL" tab.
Fill out the following.
--Identity--
Private Key Alias: demoidentity
Private Key Passphrase: DemoIdentityPassPhrase
Confirm Private Key Passphrase: DemoIdentityPassPhrase

In the "Advanced" section, choose "Client Certs requested and Enforced" for "Two Way Client Cert Behavior:".

After all these, you need to save the configuration and restart the weblogic server. Then run the following program. It should work.

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;

import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

/*
 * This example demostrates how to use a SSLSocket as client to
 * send a HTTP request and get response from an HTTPS server.
 * It assumes that the client is not behind a firewall
 * In this example, two-way SSL is used. Client also needs to present its identity.
 */

public class SSLClient {

 public void testUsingSocket() {

  String keyStore = "C:/myidentity.jks";
  String keyStorePassword = "mytest";
  System.setProperty("javax.net.ssl.keyStore", keyStore);
  System.setProperty("javax.net.ssl.keyStorePassword", keyStorePassword);
  
  // if you are running this program using jrocket JVM, then the following lines that
  // set the trustStore and trustStorePassword are not needed.
  String trustStore = "C:\\bea1032\\jrockit_160_14_R27.6.5-32\\jre\\lib\\security\\cacerts";
  String trustStorePassword = "changeit";
  System.setProperty("javax.net.ssl.trustStore", trustStore);
  System.setProperty("javax.net.ssl.trustStorePassword",trustStorePassword);

  System.setProperty("javax.net.debug", "ssl");
  String host = "localhost"; 
  int port = 7002; 
  try {
   SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory
     .getDefault();
   SSLSocket socket = (SSLSocket) factory.createSocket(host, port);

   socket.startHandshake();

   PrintWriter out = new PrintWriter(new BufferedWriter(
     new OutputStreamWriter(socket.getOutputStream())));

   out.println("GET /myapp/ HTTP/1.0");
   out.println();
   out.flush();

   /*
    * Make sure there were no surprises
    */
   if (out.checkError())
    System.out
      .println("SSLSocketClient:  java.io.PrintWriter error");

   /* read response */
   BufferedReader in = new BufferedReader(new InputStreamReader(socket
     .getInputStream()));

   String inputLine;
   while ((inputLine = in.readLine()) != null)
    System.out.println(inputLine);

   in.close();
   out.close();
   socket.close();

  } catch (Exception e) {
   e.printStackTrace();
  }
 }

public void testUsingURL() throws Exception {

  javax.net.ssl.HttpsURLConnection
    .setDefaultHostnameVerifier(new javax.net.ssl.HostnameVerifier() {

     public boolean verify(String hostname,
       javax.net.ssl.SSLSession sslSession) {
      if (hostname.equals("localhost")) {
       return true;
      }
      return false;
     }
    });

  String keyStore = "C:/bea1032/wlserver_10.3/server/lib/DemoIdentity.jks";
  String keyStorePassword = "DemoIdentityKeyStorePassPhrase";

  keyStore = "C:/workshop/java/security/myidentity.jks";
  keyStorePassword = "mytest";

  System.setProperty("javax.net.ssl.keyStore", keyStore);
  System.setProperty("javax.net.ssl.keyStorePassword", keyStorePassword);

  URL myUrl = new URL("https://localhost:7002/myapp");
  BufferedReader in = new BufferedReader(new InputStreamReader(myUrl
    .openStream()));

  String inputLine;

  while ((inputLine = in.readLine()) != null)
   System.out.println(inputLine);

  in.close();
 }

 public static void main(String[] args) throws Exception {
  SSLClient p = new SSLClient();
  p.testUsingSocket();
  p.testUsingURL();
 }
}

Note that in the example above, the testUsingURL() method needs to set the HostnameVerifier to accept "localhost". Otherwise it will throw an exception. But the testUsingSocket() method does not need this. So there must be something different underneath in the Socket implementation.

References

  1. http://docs.oracle.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html

Wednesday, October 30, 2013

Use URL class to talk HTTP and HTTPS through proxy

The example below shows how to use the java URL class to talk to HTTP/HTTPS web servers. If your machine connects to the internet through a proxy, the hostname and the port number of the proxy need to be passed to the URL class.

One way to find the proxy is to use the web browser. As an example, in IE, you can go to Tools --> Internet Options --> Connections --> Lan settings. In my case, it shows that the checkbox "Use automatic configurtion script" is chosen. By looking at the script, I can find the proxy hostname and port number. In the code below, I just use "your.proxy.host" and "your.proxy.port". Note that the system property names are different depending on if you are connecting to HTTP or HTTPS. But the proxy host and port number are the same.

When this program is run, it should print out the contents of two HTML files, one for HTTP(http://example.com), and the other for HTTPS(https://verisign.com).

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;

public class TestURL {

 public void testHttpURL() {
  System.out.println("\ntestHttpURL()");

  System.setProperty("http.proxyHost", "your.proxy.host");
  System.setProperty("http.proxyPort", "your.proxy.port");
  String hostName = "http://example.com";
  try {
   URL hp = new URL(hostName);
   URLConnection urlConn = hp.openConnection();
   System.out.println("urlConn is: " + urlConn);
   HttpURLConnection hpCon = (HttpURLConnection) urlConn;

   InputStream obj = (InputStream) hpCon.getInputStream();
   BufferedReader in = new BufferedReader(new InputStreamReader(obj));

   String inputLine;

   while ((inputLine = in.readLine()) != null)
    System.out.println(inputLine);
  } catch (Exception ex) {
   ex.printStackTrace();
  }
 }

 public void testHttpsURL() {
  System.out.println("\ntestHttpsURL()");

  System.setProperty("https.proxyHost", "your.proxy.host");
  System.setProperty("https.proxyPort", "your.proxy.port");

  String trustStore = "C:\\bea1032\\jrockit_160_14_R27.6.5-32\\jre\\lib\\security\\cacerts";
  String trustStorePassword = "changeit";
  System.setProperty("javax.net.ssl.trustStore", trustStore);
  System.setProperty("javax.net.ssl.trustStorePassword",trustStorePassword);

  String hostName = "https://verisign.com";
  try {
   URL hp = new URL(hostName);
   URLConnection urlConn = hp.openConnection();
   System.out.println("urlConn is: " + urlConn);
   HttpURLConnection hpCon = (HttpURLConnection) urlConn;

   InputStream obj = (InputStream) hpCon.getInputStream();
   BufferedReader in = new BufferedReader(new InputStreamReader(obj));

   String inputLine;
   while ((inputLine = in.readLine()) != null)
    System.out.println(inputLine);
  } catch (Exception ex) {
   ex.printStackTrace();
  }
 }

 public static void main(String args[]) {
  TestURL p = new TestURL();
  p.testHttpURL();
  p.testHttpsURL();
 }
}

Note that in the code for HTTPS, the trustStore and its password values are the default values used by java. So those lines can be commented out. You can however set trustStore to an empty value "" to see what will happen. An exception will be thrown. So that shows that the code does need the trust store. If you are connecting to a HTTPS web site and the default java trustStore cacerts does not contain the certificates to trust that web site, you will need to customize your trust store so the HTTPS connection can be successful.

References

  1. http://docs.oracle.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html

Thursday, September 12, 2013

Blog's Fourth Anniversay

Today is the fourth year anniversary of this blog. It is cloudy. The current temperature is 76F. This summer in Pittsburgh has been rainy and not very hot. But yesterday was quite humid with high temperature. I planted one seedling for small tomato in the garden the first time this year. I have harvested about 60 so far.

I just came back from seeing the dentist. I was recommended to have a tooth guard. Recently I have spent quite some time studying algorithms and JMS.

Tuesday, September 10, 2013

Spring JMS

The General Spring Bean Life Cycle in a Web Application

The java web application provides a plugin point in the web.xml for the user to supply his own context. It is the <listener> tag where a user can put his own class that implements the interface javax.servlet.ServletContextListener. The implementation in Spring is the ContextLoaderListener class. And the user can pass additional parameter values to his listener using the <context-param> tag. The following is an example:

<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>
            classpath:com/xyz/dao/applicationContext-dao.xml    
            classpath:com/xyz/jms/applicationContext-jms.xml    
  </param-value>
 </context-param>

 <listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>

Bean Creation

The ContextLoaderListener uses org.springframework.web.context.ContexLoader by default to perform the actual initialization work for the root application context.

ContextLoaderListener implements the following API method from the interface ServletContextListener. And this method will create the Spring beans when the web application is started.

public void contextInitialized(ServletContextEvent event) {
  this.contextLoader = createContextLoader();
  this.contextLoader.initWebApplicationContext(event.getServletContext());
 }
The following is the code of the method initWebApplicationContext of the class ContextLoader:
public WebApplicationContext initWebApplicationContext(ServletContext servletContext)
   throws IllegalStateException, BeansException {

  if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
   throw new IllegalStateException(
     "Cannot initialize context because there is already a root application context present - " +
     "check whether you have multiple ContextLoader* definitions in your web.xml!");
  }
                 ......
   // Determine parent for root web application context, if any.
   ApplicationContext parent = loadParentContext(servletContext);

   // Store context in local instance variable, to guarantee that
   // it is available on ServletContext shutdown.
   this.context = createWebApplicationContext(servletContext, parent);
   servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
   currentContextPerThread.put(Thread.currentThread().getContextClassLoader(), this.context);
                ......
   return this.context;
  
 }
You can see that Spring creates its own context and stores it in the standard servletContext object. This way it can be retrieved in other code from the servletContext. The code first has a call to loadParentContext. This is useful if the web module WAR is part of an EAR application. The following is the javadoc from Spring for this method:

The main reason to load a parent context here is to allow multiple root web application contexts to all be children of a shared EAR context, or alternately to also share the same parent context that is visible to EJBs. For pure web applications, there is usually no need to worry about having a parent context to the root web application context.

The following code shows how to get the Spring bean from the bean ID using the context:

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

public static Object getBean(String beanId) {
  
  FacesContext facesContext = FacesContext.getCurrentInstance();
  ServletContext servletContext = (ServletContext) facesContext
    .getExternalContext().getContext();
  WebApplicationContext webApplicationContext = WebApplicationContextUtils
    .getWebApplicationContext(servletContext);
  return webApplicationContext.getBean(beanId);
 }
The above method is used in JSF(Java Server Faces), hence the FacesContext. If you are not in JSF, you can also do similar thing as long as you have the servletConext object. Basically it will use the same attribute WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE to get the context from the servletContext. The actual code of the method getWebApplicationContext is below:
public static WebApplicationContext getWebApplicationContext(ServletContext sc) {
  return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
 }

The Spring beans are defined in xml files. How are these bean names because the actual java class objects? Spring uses the class loaders that can be got by calling Thread.currentThread().getContextClassLoader() or class.getClassLoader() to load the classes.

The Spring beans are usually singletons. For different HTTP requests from the web clients, different threads are used to serve the requests. But the beans used in these threads are the same. In Weblogic, you may see sometimes that the threads to serve the clients are also same. I think that is because Weblogic maintains a thread pool. So the same thread may be used for two different requests.

Bean Termination

ContextLoaderListener implements the following API method from the interface ServletContextListener. And this method will destroy the Spring beans when the web application is shutdown.

public void contextDestroyed(ServletContextEvent event) {
  if (this.contextLoader != null) {
   this.contextLoader.closeWebApplicationContext(event.getServletContext());
  }
 }
The following is the actual stack when I redeploy a web application to the weblogic server. You can see the call stack to create beans.
   DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton(String, ObjectFactory) line: 222 
   DefaultListableBeanFactory(AbstractBeanFactory).doGetBean(String, Class, Object[], boolean) line: 261 
   DefaultListableBeanFactory(AbstractBeanFactory).getBean(String, Class, Object[]) line: 185 
   DefaultListableBeanFactory(AbstractBeanFactory).getBean(String) line: 164 
   DefaultListableBeanFactory.preInstantiateSingletons() line: 429 
   XmlWebApplicationContext(AbstractApplicationContext).finishBeanFactoryInitialization(ConfigurableListableBeanFactory) line: 728 
   XmlWebApplicationContext(AbstractApplicationContext).refresh() line: 380 
   ContextLoader.createWebApplicationContext(ServletContext, ApplicationContext) line: 255 
   ContextLoader.initWebApplicationContext(ServletContext) line: 199 
   ContextLoaderListener.contextInitialized(ServletContextEvent) line: 45 
   EventsManager$FireContextListenerAction.run() line: 481 
   AuthenticatedSubject.doAs(AbstractSubject, PrivilegedAction) line: 321 
   SecurityManager.runAs(AuthenticatedSubject, AuthenticatedSubject, PrivilegedAction) line: 121 
   EventsManager.notifyContextCreatedEvent() line: 181 
   WebAppServletContext.preloadResources() line: 1801 
   WebAppServletContext.start() line: 3045 
   WebAppModule.startContexts() line: 1397 
   WebAppModule.start() line: 460 

JMS Sender

Send XML message using JAXB marshalling with XML schema validation

The following is the sample code to use the Spring JmsTemplate class to send the XML message. The XML message is created by marshalling a java Foo ojbect. The class Foo is a generated class from JAXB using the XSD file "your.xsd". The marshaller loads the XSD file so it will validate the XML content. If the java foo object does not create a valid message, the method "marshaller.marshal(xmlMsg, sw)" will throw exception. For example, if a field is required in the XSD file your.xsd, and the foo ojbect has null value for that field, then a SAXParseException will be thrown. The file schemas/your.xsd must be put on the classpath.

Also note that in this example, the JMS message type is BytesMessage. It also creates properties in the JMS message.

import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;

public void sendMessage(final String message, final Map properties) {
  jmsTemplate.send(new MessageCreator() {
   @Override
   public Message createMessage(Session session) throws JMSException {
    BytesMessage bytesMsg = session.createBytesMessage();
    bytesMsg.writeBytes(message.getBytes());
    if (properties != null && !properties.isEmpty()) {
     Iterator it = properties.entrySet().iterator();
     while (it.hasNext()) {
      Map.Entry entry = (Map.Entry) it.next();
      String key = (String) entry.getKey();
      String val = (String) entry.getValue();
      bytesMsg.setStringProperty(key, val);
     }
    }
    return bytesMsg;
   }
  });
 }

 public void sendMessage(Foo fooObj, final Map properties)
   throws JAXBException {
  try {
   String message = marshall(fooObj);
   this.sendMessage(message, properties);
  } catch (SAXException e) {
   throw new JAXBException(e);
  }
 }

 private String marshall(Foo fooObj) throws JAXBException,
   SAXException {
  JAXBElement xmlMsg = new com.example.schema.ObjectFactory()
    .createXYZ(fooObj);
  JAXBContext jaxbContext = JAXBContext.newInstance(Foo.class);
  Marshaller marshaller = jaxbContext.createMarshaller();
  SchemaFactory schemaFactory = SchemaFactory
    .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
  URL xsdUrl = getClass().getClassLoader().getResource(
    "schemas/your.xsd");
  Schema schema = schemaFactory.newSchema(xsdUrl);
  marshaller.setSchema(schema);
  StringWriter sw = new StringWriter();
  marshaller.marshal(xmlMsg, sw);
  return sw.toString();
 }

The Life Cycle of JMS Connection and Session

The following is a case study. The version Spring 2.5.6 is used. In the actual application code,the operations are put into a JTA transaction. The analysis below is to show how the JMS connection and session are created and closed.
  1. Spring uses JmsTemplate to send messages
  2. JmsTemplate uses the following method to actually send the message:
        public Object execute(SessionCallback action, boolean startConnection) throws JmsException {
         ...
          
         Session sessionToUse = ConnectionFactoryUtils.doGetTransactionalSession(
             getConnectionFactory(), this.transactionalResourceFactory, startConnection);
         ...
         return action.doInJms(sessionToUse);
            ...  
    
         finally {
           JmsUtils.closeSession(sessionToClose);
           ConnectionFactoryUtils.releaseConnection(conToClose, getConnectionFactory(), startConnection);
         }
       }
     
    Notes:
    (1) The "finally" block closes sessionToClose and conToClose. These are not the same as sessionToUse and its connection. When sessionToUse is not null, sessionToClose and conToClose are not created, and the "finally" block will do nothing when they are null.
    (2) I did not find a call to connection.start(). I did a separate test and it showed that the message can still be sent if start() is not invoked. But for a JMS consumer, this has to be called. Otherwise, no message will be received.
  3. The call ConnectionFactoryUtils.doGetTransactionalSession(...) creates the connection and the session. And the connection is saved into a new JmsResourceHolder() which is bound to TransactionSynchronizationManager in the following code in that method:
       TransactionSynchronizationManager.bindResource(connectionFactory, resourceHolderToUse);
     
  4. At the end of the operations, TransactionSynchronizationManager calls the following method:
          public static Object unbindResource(Object key) 
          
    Eventually the following code of class JmsResourceHolder is called:
        public void closeAll() {
          for (Iterator it = this.sessions.iterator(); it.hasNext();) {
           try {
            ((Session) it.next()).close();
           }
           catch (Throwable ex) {
            logger.debug("Could not close synchronized JMS Session after transaction", ex);
           }
          }
          for (Iterator it = this.connections.iterator(); it.hasNext();) {
           Connection con = (Connection) it.next();
           ConnectionFactoryUtils.releaseConnection(con, this.connectionFactory, true);
          }
          this.connections.clear();
          this.sessions.clear();
          this.sessionsPerConnection.clear();
     }
        
Question: What if the connection returned from the ConnectionFactory is a pooled connection? Obviously it should not be closed at the end. How does Spring know it is pooled and not close it?

One implementation I saw that solve the question above is the following. The code ConnectionFactoryUtils.releaseConnection(con, this.connectionFactory, true); will call con.close();. But the trick is in the method close(). The connection is a customer-implemented class. Its "close" method actually does not close it in all circumstances. The connection class itself has a reference to the connection factory. It will first check if connection pooling is enabled. If yes, it will just tell the factory to update the status for this connection, and that is it. Only if the pooling is not enabled, will the connection actually close itself.

Spring also has its own JMS connection pool implementation. One of them is the SingleConnectionFactory. It uses the similar way as the one mentioned above to avoid the connection being closed. It will return a connection proxy that will essentially do nothing in the "close()" method. The following is the actual code:

/**
  * Wrap the given Connection with a proxy that delegates every method call to it
  * but suppresses close calls. This is useful for allowing application code to
  * handle a special framework Connection just like an ordinary Connection from a
  * JMS ConnectionFactory.
  * @param target the original Connection to wrap
  * @return the wrapped Connection
  */
 protected Connection getSharedConnectionProxy(Connection target) {
  List classes = new ArrayList(3);
  classes.add(Connection.class);
  if (target instanceof QueueConnection) {
   classes.add(QueueConnection.class);
  }
  if (target instanceof TopicConnection) {
   classes.add(TopicConnection.class);
  }
  return (Connection) Proxy.newProxyInstance(
    Connection.class.getClassLoader(),
    (Class[]) classes.toArray(new Class[classes.size()]),
    new SharedConnectionInvocationHandler(target));
 }
The following javadoc of the class org.springframework.jms.connection.SingleConnectionFactory is also quite helfpful.
A JMS ConnectionFactory adapter that returns the same Connection from all 
createConnection() calls, and ignores calls to Connection.close(). According to the
 JMS Connection model, this is perfectly thread-safe (in contrast to e.g. JDBC). The 
shared Connection can be automatically recovered in case of an Exception. 

You can either pass in a specific JMS Connection directly or let this factory lazily 
create a Connection via a given target ConnectionFactory. This factory generally works
 with JMS 1.1 as well as the JMS 1.0.2 API. 

...

Useful for testing and standalone environments in order to keep using the same 
Connection for multiple JmsTemplate calls, without having a pooling ConnectionFactory
 underneath. This may span any number of transactions, even concurrently executing 
transactions. 

Note that Spring's message listener containers support the use of a shared Connection
 within each listener container instance. Using SingleConnectionFactory in combination
 only really makes sense for sharing a single JMS Connection across multiple listener
 containers. 

So the answer to the original question may be the following. Spring actually does not detect if a connection returned from a connection factory is pooled or not. It just calls its "close" method. It lets the connection class itself to decide whether or not to close the actual connection.

JMS Consumer

The Life Cycle of JMS Connection and Session

Spring uses DefaultMessageListenerContainer to receiver messages. An example is as follows:
<bean id="jmsContainer"
  class="org.springframework.jms.listener.DefaultMessageListenerContainer">
  <property name="connectionFactory" ref="jmsDestConnectionFactory" />
  <property name="destination" ref="myDestination" />
  <property name="sessionAcknowledgeModeName" value="AUTO_ACKNOWLEDGE" />
  <property name="messageListener" ref="messageListener" />
  <property name="sessionTransacted" value="true" />
  <property name="concurrentConsumers" value="1"></property>
 </bean>
The main steps are the following.
  1. When the bean is created, the JMS connection and session are created. The connection is also started.
  2. The conneciton will be reused by the application. When the application is shutdown, the connection will be stopped and then closed.
The following are the main steps that the JMS connection is closed.
  1. org.springframework.web.context.ContextLoader calls
        public void closeWebApplicationContext(ServletContext servletContext) {...}
    
  2. The method above will call
     protected void doClose() {
          ...
           Map lifecycleBeans = getLifecycleBeans();
           for (Iterator it = new LinkedHashSet(lifecycleBeans.keySet()).iterator(); it.hasNext();) {
            String beanName = (String) it.next();
            doStop(lifecycleBeans, beanName);
           }
           // Destroy all cached singletons in the context's BeanFactory.
           destroyBeans();
           // Close the state of this context itself.
           closeBeanFactory();
           onClose();
           synchronized (this.activeMonitor) {
            this.active = false;
           }
          }
     }
    
    In the above code, the "doStop()" method will stop the connection, and the "destoryBeans()" will close the connection

What Happens Internally in JMS Connection and Session?

So how are the messages actually sent over the network? We have to use open source code to get some idea. I looked at ActiveMQ, which is a popular open source JMS implementation. The basic steps to send a message are as follows:

  1. MessageProducer invokes the "send(...)" method.
  2. The MessageProducer implementation actually has a reference to the session. So its "send" method will call "session.send(...)"
  3. The session implementation actually has a reference to the connection. So it calls "connection.synSendPacket(...)" or "connection.aSyncSendPacket(...)".
  4. The connection object will delegate the task to some transport layer object to actually send the message. And eventually I saw in a place that it uses ObjectOutputStream to send out the message.
Other observations on ActiveMQ.
  1. A connection holds references to all the sessions that it has created.
  2. A session holds references to all the consumers that it has created.
  3. When a connection is started, it calls the "start()" method of all its sessions.
  4. When a session is started, it calls the "start()" method of all its consumers. Also it calls "executor.start()". The executor is of class ActiveMQSessionExecutor. Its "start()" method has the following main code line:
       messageQueue.start();
    
    The messageQueue here is of class MessageDispatchChannel.
  5. The "start()" method of the consumer has the following main code lines:
          unconsumedMessages.start();
          session.executor.wakeup();
    
    The unconsumerdMessages is an instance of MessageDispatchChannel.
  6. The MessageDispatchChannel interface has the "enqueue" and "dequeue" methods. One implementation of this interface has a list of MessageDispatch, which has an instance variable of Message. So this list can be used to store and send messages. But there must be other ways such as using files or a database to store the messages. I am not clear here.

Transaction for Spring JMS consumer

The general JMS API specifies that when you create a session, you specify whether it is transacted. The first argument to the createSession method is a boolean value. A value of true means that the session is transacted; a value of false means that it is not transacted. The second argument to this method is the acknowledge mode, which is relevant only to nontransacted sessions. If the session is transacted, the second argument is ignored.

The commit and the rollback methods for local transactions are associated with the session.

In an Enterprise JavaBeans component, you cannot use the Session.commit and Session.rollback methods. Instead, you use distributed transactions.

Now for Spring class org.springframework.jms.listener.DefaultMessageListenerContainer, it has the properties transactionManager, sessionAcknowledgeModeName and sessionTransacted. The logic about how these properties are used are the following:

  1. If the property "transactionManager" is set, then that transaction manager will be used. The property "sessionTransacted" will be ignored.
  2. Else if "sessionTransacted" is set to "true", local transaction will be used. And the property "sessionAcknowledgeModeName" will be ignored. Programs need to use session.commit or session.rollback to manage the transaction.
  3. Else there is no transaction. The property "sessionAcknowledgeModeName" comes into effect.
The javadoc[1] of Spring recommends the following:
  1. The general recommendation is to set "sessionTransacted" to "true", typically in combination with local database transactions triggered by the listener implementation, through Spring's standard transaction facilities. This will work nicely in Tomcat or in a standalone environment, often combined with custom duplicate message detection (if it is unacceptable to ever process the same message twice).
  2. Alternatively, specify a JtaTransactionManager as "transactionManager" for a fully XA-aware JMS provider - typically when running on a J2EE server, but also for other environments with a JTA transaction manager present. This will give full "exactly-once" guarantees without custom duplicate message checks, at the price of additional runtime processing overhead.

    Note that it is also possible to specify a JmsTransactionManager as external "transactionManager", providing fully synchronized Spring transactions based on local JMS transactions. The effect is similar to "sessionTransacted" set to "true", the difference being that this external transaction management will also affect independent JMS access code within the service layer (e.g. based on JmsTemplate or TransactionAwareConnectionFactoryProxy), not just direct JMS Session usage in a SessionAwareMessageListener.

Note from [1] about how the exception is handled for the class AbstractMessageListenerContainer, which is an upper class of DefaultMessageListenerContainer: "NOTE: The default behavior of this message listener container is to never propagate an exception thrown by a message listener up to the JMS provider. Instead, it will log any such exception at the error level. This means that from the perspective of the attendant JMS provider no such listener will ever fail."

The Duplicate Messages Issue

Again from [1], I think the following is true for the DefaultMessageListenerContainer. Note that cases #4, #5 and #6 are only effective when no transaction manager or local transaction is used. If a transactionManager is set or the sessionTransacted is set to "true", the AcknowledgeMode will be ignored.
  1. If a JtaTransactionManager as "transactionManager" for a fully XA-aware JMS provider, it will give full "exactly-once" guarantees without custom duplicate message checks
  2. To specify a JmsTransactionManager as external "transactionManager". The javadoc does not explicitly say if there will be duplicate messages. But it says this case is similar to "sessionTransacted" set to "true", in which case the duplicate messaegs are possible.
  3. To set "sessionTransacted" to "true". In this case, the duplicate messages are possible because the javadoc there says this case is "often combined with custom duplicate message detection"
  4. "sessionAcknowledgeMode" set to "AUTO_ACKNOWLEDGE" (default): Automatic message acknowledgment before listener execution; no redelivery in case of exception thrown.
  5. "sessionAcknowledgeMode" set to "CLIENT_ACKNOWLEDGE": Automatic message acknowledgment after successful listener execution; no redelivery in case of exception thrown.
  6. "sessionAcknowledgeMode" set to "DUPS_OK_ACKNOWLEDGE": Lazy message acknowledgment during or after listener execution; potential redelivery in case of exception thrown.
Also note that the javadoc has the following regarding the above acknowledge modes: "The exact behavior might vary according to the concrete listener container and JMS provider used."

Appendix

To see more about the steps of how a Spring bean is created, the following complete stack trace is helpful. The stack is obtained by putting a break point in the code and redeploying the web application to the weblogic server that is started in debug mode.
Oracle WebLogic Server 11gR1 PatchSet 1 at localhost [Oracle WebLogic Launch Configuration] 
 Java HotSpot(TM) Client VM[localhost:8453] 
  Daemon Thread [DynamicListenThread[Default]] (Running) 
  Daemon Thread [DynamicListenThread[Default[2]]] (Running) 
  Daemon Thread [DynamicListenThread[Default[3]]] (Running) 
  Daemon Thread [DynamicListenThread[Default[1]]] (Running) 
  Daemon Thread [[STANDBY] ExecuteThread: '4' for queue: 'weblogic.kernel.Default (self-tuning)'] (Running) 
  Daemon Thread [weblogic.GCMonitor] (Running) 
  Daemon Thread [TIBCO EMS TCPLink Reader (Server-47729)] (Running) 
  Daemon Thread [TIBCO EMS Connections Pinger] (Running) 
  Daemon Thread [Timer-2] (Suspended (exception NoClassDefFoundError)) 
   TimerThread.run() line: 468 
  Daemon Thread [FooJMSStarvedConsumerTimer] (Running) 
  Daemon Thread [[ACTIVE] ExecuteThread: '3' for queue: 'weblogic.kernel.Default (self-tuning)'] (Running) 
  Daemon Thread [Monitor Runner] (Running) 
  Daemon Thread [Session Monitor] (Running) 
  Daemon Thread [Session Monitor] (Running) 
  Daemon Thread [[STANDBY] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'] (Suspended (breakpoint at line 37 in SampleProducer)) 
   SampleProducer.setJmsTemplate(JmsTemplate) line: 37 
   NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method] 
   NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39 
   DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25 
   Method.invoke(Object, Object...) line: 597 
   BeanWrapperImpl.setPropertyValue(BeanWrapperImpl$PropertyTokenHolder, PropertyValue) line: 840 
   BeanWrapperImpl.setPropertyValue(PropertyValue) line: 651 
   BeanWrapperImpl(AbstractPropertyAccessor).setPropertyValues(PropertyValues, boolean, boolean) line: 78 
   BeanWrapperImpl(AbstractPropertyAccessor).setPropertyValues(PropertyValues) line: 59 
   DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).applyPropertyValues(String, BeanDefinition, BeanWrapper, PropertyValues) line: 1276 
   DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).populateBean(String, AbstractBeanDefinition, BeanWrapper) line: 1010 
   DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).doCreateBean(String, RootBeanDefinition, Object[]) line: 472 
   AbstractAutowireCapableBeanFactory$1.run() line: 409 
   AccessController.doPrivileged(PrivilegedAction, AccessControlContext) line: not available [native method] 
   DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBean(String, RootBeanDefinition, Object[]) line: 380 
   AbstractBeanFactory$1.getObject() line: 264 
   DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton(String, ObjectFactory) line: 222 
   DefaultListableBeanFactory(AbstractBeanFactory).doGetBean(String, Class, Object[], boolean) line: 261 
   DefaultListableBeanFactory(AbstractBeanFactory).getBean(String, Class, Object[]) line: 185 
   DefaultListableBeanFactory(AbstractBeanFactory).getBean(String) line: 164 
   DefaultListableBeanFactory.findAutowireCandidates(String, Class, DependencyDescriptor) line: 671 
   DefaultListableBeanFactory.resolveDependency(DependencyDescriptor, String, Set, TypeConverter) line: 610 
   AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(Object, String, PropertyValues) line: 499 
   InjectionMetadata.injectMethods(Object, String, PropertyValues) line: 117 
   AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(PropertyValues, PropertyDescriptor[], Object, String) line: 253 
   DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).populateBean(String, AbstractBeanDefinition, BeanWrapper) line: 998 
   DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).doCreateBean(String, RootBeanDefinition, Object[]) line: 472 
   AbstractAutowireCapableBeanFactory$1.run() line: 409 
   AccessController.doPrivileged(PrivilegedAction, AccessControlContext) line: not available [native method] 
   DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBean(String, RootBeanDefinition, Object[]) line: 380 
   AbstractBeanFactory$1.getObject() line: 264 
   DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton(String, ObjectFactory) line: 222 
   DefaultListableBeanFactory(AbstractBeanFactory).doGetBean(String, Class, Object[], boolean) line: 261 
   DefaultListableBeanFactory(AbstractBeanFactory).getBean(String, Class, Object[]) line: 185 
   DefaultListableBeanFactory(AbstractBeanFactory).getBean(String) line: 164 
   DefaultListableBeanFactory.preInstantiateSingletons() line: 429 
   XmlWebApplicationContext(AbstractApplicationContext).finishBeanFactoryInitialization(ConfigurableListableBeanFactory) line: 728 
   XmlWebApplicationContext(AbstractApplicationContext).refresh() line: 380 
   ContextLoader.createWebApplicationContext(ServletContext, ApplicationContext) line: 255 
   ContextLoader.initWebApplicationContext(ServletContext) line: 199 
   ContextLoaderListener.contextInitialized(ServletContextEvent) line: 45 
   EventsManager$FireContextListenerAction.run() line: 481 
   AuthenticatedSubject.doAs(AbstractSubject, PrivilegedAction) line: 321 
   SecurityManager.runAs(AuthenticatedSubject, AuthenticatedSubject, PrivilegedAction) line: 121 
   EventsManager.notifyContextCreatedEvent() line: 181 
   WebAppServletContext.preloadResources() line: 1801 
   WebAppServletContext.start() line: 3045 
   WebAppModule.startContexts() line: 1397 
   WebAppModule.start() line: 460 
   ModuleStateDriver$3.next(Object) line: 425 
   StateMachineDriver.nextState(StateChange, Object[]) line: 83 
   ModuleStateDriver.start(Module[]) line: 119 
   ScopedModuleDriver.start() line: 200 
   ModuleListenerInvoker.start() line: 247 
   ModuleStateDriver$3.next(Object) line: 425 
   StateMachineDriver.nextState(StateChange, Object[]) line: 83 
   ModuleStateDriver.start(Module[]) line: 119 
   StartModulesFlow.activate() line: 27 
   BaseDeployment$2.next(Object) line: 1267 
   StateMachineDriver.nextState(StateChange, Object[]) line: 83 
   WarDeployment(BaseDeployment).activate(DeploymentContext) line: 409 
   WarDeployment(SingleModuleDeployment).activate(DeploymentContext) line: 39 
   DeploymentStateChecker.activate(DeploymentContext) line: 161 
   AppContainerInvoker.activate(DeploymentContext) line: 79 
   RedeployOperation(AbstractOperation).activate(Deployment) line: 569 
   RedeployOperation(ActivateOperation).activateDeployment() line: 150 
   RedeployOperation(ActivateOperation).doCommit() line: 116 
   RedeployOperation(AbstractOperation).commit() line: 323 
   DeploymentManager.handleDeploymentCommit(Deployment, AbstractOperation) line: 844 
   DeploymentManager.activateDeploymentList(ArrayList, DeploymentManager$DeploymentRequestInfo) line: 1253 
   DeploymentManager.handleCommit(DeploymentContext) line: 440 
   DeploymentServiceDispatcher.commit(DeploymentContext) line: 163 
   DeploymentReceiverCallbackDeliverer.doCommitCallback(DeploymentContext) line: 181 
   DeploymentReceiverCallbackDeliverer.access$100(DeploymentReceiverCallbackDeliverer, DeploymentContext) line: 12 
   DeploymentReceiverCallbackDeliverer$2.run() line: 67 
   SelfTuningWorkManagerImpl$WorkAdapterImpl.run() line: 516 
   ExecuteThread.execute(Runnable) line: 201 
   ExecuteThread.run() line: 173 
  Daemon Thread [AS400 Read Daemon [system:pitt2;job:114314/QUSER/QZDASOINIT]] (Running) 
  Daemon Thread [AS400 Read Daemon [system:tst1;job:113896/QUSER/QZDASOINIT]] (Running) 
  Daemon Thread [Thread-11] (Running) 
  Daemon Thread [DoSManager] (Running) 
  Daemon Thread [VDE Transaction Processor Thread] (Running) 
  Daemon Thread [ExecuteThread: '3' for queue: 'weblogic.socket.Muxer'] (Running) 
  Daemon Thread [ExecuteThread: '2' for queue: 'weblogic.socket.Muxer'] (Running) 
  Daemon Thread [ExecuteThread: '1' for queue: 'weblogic.socket.Muxer'] (Running) 
  Daemon Thread [ExecuteThread: '0' for queue: 'weblogic.socket.Muxer'] (Running) 
  Daemon Thread [Thread-7] (Running) 
  Daemon Thread [[ACTIVE] ExecuteThread: '1' for queue: 'weblogic.kernel.Default (self-tuning)'] (Running) 
  Daemon Thread [weblogic.timers.TimerThread] (Running) 
  Daemon Thread [weblogic.time.TimeEventGenerator] (Running) 
  Daemon Thread [[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)'] (Running) 
  Daemon Thread [Timer-1] (Running) 
  Daemon Thread [Timer-0] (Running) 
  Thread [main] (Running) 
  Daemon Thread [FooJMSStarvedConsumerTimer] (Running) 
 Weblogic Server 
new hap-ws LDEV [Maven Build] 
 C:\bea1032\jdk160_14_R27.6.5-32\bin\javaw.exe (Sep 10, 2013 4:59:32 PM) 

References

  1. http://docs.spring.io/spring/docs/2.5.6/api/org/springframework/jms/listener/AbstractMessageListenerContainer.html

Friday, September 6, 2013

Partition, File System, Directory, etc

Partition and File System

Found the following link that has good explanations on partition, file system, etc. Though it is about UNIX, the concepts on LINUX should be similar.
http://www.freebsd.org/doc/handbook/disk-organization.html

The main points are the following.

  1. Directories and files are stored in a file system. Each file system contains exactly one directory at the very top level, called the root directory for that file system.
  2. One file system is designated the root file system or /. Every other file system is mounted under the root file system.
  3. No matter how many disks are on the FreeBSD system, every directory appears to be part of the same disk.
  4. File systems can be mounted on top of one another.
  5. File systems are contained in partitions.
  6. Each partition can contain only one file system.
  7. File systems are a fixed size.

You can use the command "df" to get the information of the file systems on a server. The following is an example on a LINUX server.

$ df -T
Filesystem    Type   1K-blocks      Used Available Use% Mounted on
/dev/sda3     ext3     3882516   2032072   1650036  56% /
/dev/mapper/vg00-optvol
              ext3     8125880   2049796   5656656  27% /opt
/dev/mapper/vg00-homevol
              ext3     1015704     34176    929100   4% /home
/dev/mapper/vg00-varvol
              ext3     8125880   1960524   5745928  26% /var
/dev/sda1     ext3      194410     17867    166506  10% /boot
tmpfs        tmpfs     1956764         0   1956764   0% /dev/shm
tmpfs        tmpfs     2097152      3716   2093436   1% /tmp
/dev/mapper/vg01-lvol1
              ext3     1032088     34936    944724   4% /opt/abc
/dev/mapper/vg01-lvol2
              ext3     1032088     34100    945560   4% /var/abc
/dev/mapper/vg00-UsrLclHmVol
              ext3     5160576   1566824   3331608  32% /usr/local/home
/dev/mapper/vg01-AppOptVol
              ext3    10321208    399984   9396936   5% /opt/abc/hzm
/dev/mapper/vg01-AppVarVol
              ext3    10321208   1388868   8408052  15% /var/abc/hzm
pghplnxl01:/export/kickstart
               nfs   131272224 120520768   4086592  97% /mnt/install

In the above example, the Type values are mostly "ext3". This does not have to be true. The following example is from Reference[3]
$ df -T
Filesystem    Type   1K-blocks      Used Available Use% Mounted on
/dev/sda1     ext4   132239776   6210892 119311496   5% /
tmpfs        tmpfs     4021876         0   4021876   0% /dev/shm
/dev/sdb2     ext2    30969600    117740  29278696   1% /home/oracle
/dev/sdc1     ext2   576310180     71232 546964104   1% /home/data

Swap Space

  1. Linux has two forms of swap space: the swap partition and the swap file.The swap partition is an independent section of the hard disk used solely for swapping; no other files can reside there. The swap file is a special file in the filesystem that resides amongst your system and data files.
  2. To see what swap space you have, use the command "swapon -s".

The following is an example to find the swap space. It is performed on the same machine as in the above section.

$ /sbin/swapon -s
Filename                                Type            Size    Used    Priority
/dev/sda2                               partition       457824  457820  -1

The output above shows a partition. It is not a swap file.
Note that the "df -T" command will not show the partition information.

Find Sizes of the Files

The command "du" can be used to find the estimated file space usage. The following command will write counts for all files and sub-directories under the current directory.
du -a

References

  1. http://www.ibm.com/developerworks/linux/library/l-lpic1-v3-104-1/index.html
  2. http://www.linux.com/news/software/applications/8208-all-about-linux-swap-space
  3. http://www.thegeekstuff.com/2012/05/df-examples