Tag: JBoss AS6

Implementing UsernameToken in WebService with Basic Authentication in JBoss AS6

Hi,

Securing WebService is one of the most basic requirement while developing and testing webservices. There are various ways for securing webservice applications. One of the technique is Securing WebServices using UserNameToken. In this technique of securing webservices the client sets a SOAP header in every request that contains a username and password. The password is sent in the header in plain text. To be secure all HTTP requests and responses should be SSL encrypted.

In this example we will see how we can secure a WebService which is going to be deployed on JBoss AS6 5.1.

Step1). Create a directory somewhere in your file system with some name like “C:/UserNameToken_WebService”. then create two directories with name “src” and “clientSrc” inside “UserNameToken_WebService” directory.

Step2). Write the WebService End point “UsernameEndpoint.java” inside “C:/UserNameToken_WebService/src” directory as following:

package wssecurity;
import javax.jws.WebMethod;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;

@WebService(name = "UsernameEndpoint", targetNamespace = "http://wssecurity")
@SOAPBinding(style = SOAPBinding.Style.RPC)
public interface UsernameEndpoint
  {
    @WebMethod
    @WebResult(partName = "return")
    public String getUsernameToken();

  }

Step3). Write the Service implementation class “UsernameBean.java” program inside “C:/UserNameToken_WebService/src” directory like following:

package wssecurity;
import java.security.Principal;
import javax.annotation.Resource;
import javax.jws.WebMethod;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.xml.ws.WebServiceContext;
import org.jboss.ws.annotation.EndpointConfig;

@WebService(name = "UsernameEndpoint", serviceName = "UsernameService", targetNamespace = "http://wssecurity")
@EndpointConfig(configName = "Standard WSSecurity Endpoint")
@SOAPBinding(style = SOAPBinding.Style.RPC)
NOTE:e If you will not set fork="true"    in the client's run target (as mentioned in line-150 of above script) then the jvmargs wil be ignored
public class UsernameBean
{
   @Resource
   WebServiceContext wsCtx;

   @WebMethod
   @WebResult(partName = "return")
   public String getUsernameToken()
   {
      Principal principal = wsCtx.getUserPrincipal();
      System.out.println("nt[WebService- UsernameBean] getUsernameToken: " + principal);
      return "Hello User: "+principal.toString();
   }
}

Step4). Write the “jboss-wsee-server.xml” if you want to add any additional security feature for your webservice. Put it inside inside “C:/UserNameToken_WebService/src” directory like following (Currently it does not have anything specific to WSSE):

<?xml version="1.0" encoding="UTF-8"?>
<jboss-ws-security xmlns="http://www.jboss.com/ws-security/config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.jboss.com/ws-security/config http://www.jboss.com/ws-security/schema/jboss-ws-security_1_0.xsd">
</jboss-ws-security>

Step5). Create a “web.xml” file inside “C:/UserNameToken_WebService/src” to describe the WebService servlet declaration like following:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">
  <servlet>
    <servlet-name>UsernameService</servlet-name>
    <servlet-class>org.jboss.wsf.stack.jbws.EndpointServlet</servlet-class>
    <init-param>
      <param-name>jboss.ws.endpoint</param-name>
      <param-value>wssecurity.UsernameBean</param-value>
    </init-param>
  </servlet>

  <servlet-mapping>
    <servlet-name>UsernameService</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>

  <security-constraint>
    <web-resource-collection>
      <web-resource-name>UsernameService</web-resource-name>
      <url-pattern>/*</url-pattern>
      <http-method>GET</http-method>
      <http-method>POST</http-method>
    </web-resource-collection>
    <auth-constraint>
      <role-name>friend</role-name>
    </auth-constraint>
  </security-constraint>
  <login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>JBossWS</realm-name>
  </login-config>
  <security-role>
    <role-name>friend</role-name>
  </security-role>
</web-app>

Step6). Create a “jboss-web.xml” file inside “C:/UserNameToken_WebService/src” to describe the define the security Domain configuration for your webservice authentication/authorization purpose like following:

<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
  <security-domain>java:/jaas/JBossWS</security-domain>
</jboss-web>

NOTE: Here we are using the default web service security domain policy, which is configured already inside “$PROFILE/conf/login-config.xml” file as following:

<?xml version="1.0" encoding="UTF-8"?>
  <application-policy name="JBossWS">
    <authentication>
      <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag="required">
        <module-option name="usersProperties">props/jbossws-users.properties</module-option>
        <module-option name="rolesProperties">props/jbossws-roles.properties</module-option>
        <module-option name="unauthenticatedIdentity">anonymous</module-option>
      </login-module>
    </authentication>
  </application-policy>

NOTE: And the username and password’s are mentioned in “$PROFILE/conf/props/jbossws-users.properties” this username/password is COMMENTED in this file …So please uncomment it. You can follow previous directory as following the previously posted articles if you want to create your own roles and users and application-policies:

Step7). Now we will write the Client “SimpleUsernameTestCase.java” inside “C:/UserNameToken_WebService/clientSrc” directory as following:

package client.wssecurity;
import java.io.File;
import java.net.URL;
import java.util.Map;
import javax.xml.namespace.QName;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.Service;
import org.jboss.ws.core.StubExt;
import org.jboss.wsf.test.JBossWSTestSetup;

public class SimpleUsernameTestCase
{
   private static UsernameEndpoint port;
    public static void main(String ar[]) throws Exception
    {
         SimpleUsernameTestCase client=new SimpleUsernameTestCase();

         URL wsdlURL = client.getClass().getClassLoader().getResource("META-INF/wsdl/UsernameTokenService.wsdl");  //new File("META-INF/wsdl/UsernameService.wsdl").toURL();
         URL securityURL = client.getClass().getClassLoader().getResource("META-INF/jboss-wsse-client.xml");
         System.out.println("WSDL URL: "+wsdlURL);
         System.out.println("Security URL: "+securityURL);

         System.out.println(" org.jboss.ws.core.StubExt loaded .." + org.jboss.ws.core.StubExt.class.getProtectionDomain().getCodeSource().getLocation());
         QName serviceName = new QName("http://wssecurity", "UsernameService");
         Service service = Service.create(wsdlURL, serviceName);

         port = (UsernameEndpoint)service.getPort(UsernameEndpoint.class);
         System.out.println("nt2 ");

         ((org.jboss.ws.core.StubExt)port).setSecurityConfig(securityURL.toExternalForm());
         ((org.jboss.ws.core.StubExt)port).setConfigName("Standard WSSecurity Client");

         System.out.println("nt3 ");
         Map<String, Object> reqContext = ((BindingProvider)port).getRequestContext();
         reqContext.put(BindingProvider.USERNAME_PROPERTY, "kermit");
         reqContext.put(BindingProvider.PASSWORD_PROPERTY, "thefrog");
         System.out.println("nt4 ");
         String retObj = port.getUsernameToken();
         System.out.println("nt5 Call Successfuly Made.");
    }
}

Step8). Just incase if you want to add some security related informations from Client side as well in that case you can place the following file at client side. So create a file with name “C:/UserNameToken_WebService/clientSrc/META-INF/jboss-wsse-client.xml” like following:

<?xml version="1.0" encoding="UTF-8"?>
<jboss-ws-security xmlns="http://www.jboss.com/ws-security/config"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.jboss.com/ws-security/config http://www.jboss.com/ws-security/schema/jboss-ws-security_1_0.xsd">
  <config>
      <username/>
  </config>
</jboss-ws-security>

Step9). Now write the ant build script “build.xml” file inside “C:/UserNameToken_WebService” as following:

<project name="JBoss_Service" default="post-deploy">
<property name="jboss.home" value="/home/userone/JBoss_All/jboss-AS6/jboss-as" />
<property name="jboss.profile" value="${jboss.home}/server/default_Audit" />
<property name="java.home.dir" value="/home/userone/MyJdks/jdk1.6.0_05" />
<property name="basedir" value="." />
<property name="war.name" value="UsernameTokenService.war" />
<property name="src.dir" value="src" />
<property name="client.src.dir" value="${basedir}/clientSrc" />
<property name="dest.dir" value="build" />
<property name="client.dir" value="${basedir}/clientStuff" />
<property name="client.jar.name" value="usernameTokenClient.jar" />

<path id="jboss.classpath">
   <fileset dir="${jboss.home}/lib/endorsed">
      <include name="*.jar"/>
   </fileset>
   <fileset dir="${jboss.home}/common/lib">
      <include name="*.jar"/>
   </fileset>
   <fileset dir="${jboss.home}/lib">
      <include name="*.jar"/>
   </fileset>
   <fileset dir="${jboss.home}/client">
      <include name="*.jar"/>
      <!-- this Jar contains "org.jboss.ws.annotation.EndpointConfig"  -->
   </fileset>
   <fileset dir="${java.home.dir}/jre/lib">
       <include name="rt.jar" />
   </fileset>
   <fileset dir="${java.home.dir}/lib">
       <include name="tools.jar" />
   </fileset>
</path>

<path id="jboss.client.classpath">
   <fileset dir="${jboss.home}/lib/endorsed">
      <include name="*.jar"/>
   </fileset>

   <fileset dir="${jboss.home}/client">
      <include name="activation.jar"/>
      <include name="getopt.jar"/>
      <include name="wstx.jar"/>
      <include name="jbossall-client.jar"/>
      <include name="log4j.jar"/>
      <include name="mail.jar"/>
      <include name="jbossws-spi.jar"/>
      <include name="jbossws-common.jar"/>
      <include name="jbossws-framework.jar"/>

      <!--# Shared jaxws libs -->
      <include name="jaxws-tools.jar"/>
      <include name="jaxws-rt.jar"/>
      <include name="stax-api.jar"/>
      <include name="jaxb-api.jar"/>
      <include name="jaxb-impl.jar"/>
      <include name="jaxb-xjc.jar"/>
      <include name="streambuffer.jar"/>
      <include name="stax-ex.jar"/>

      <!--# Stack specific dependencies -->
      <include name="javassist.jar"/>
      <include name="jboss-xml-binding.jar"/>
      <include name="jbossws-native-client.jar"/>
      <include name="jbossws-native-core.jar"/>
      <include name="jbossws-native-jaxws.jar"/>
      <include name="jbossws-native-jaxws-ext.jar"/>
      <include name="jbossws-native-jaxrpc.jar"/>
      <include name="jbossws-native-saaj.jar"/>
   </fileset>

</path>

        <taskdef name="apt" classname="com.sun.tools.ws.ant.Apt">
 	  <classpath refid="jboss.classpath"/>
	</taskdef>
        <taskdef name="wsimport" classname="com.sun.tools.ws.ant.WsImport">
          <classpath refid="jboss.classpath"/>
        </taskdef>

        <target name="prepare">
           <delete dir="${dest.dir}" />
           <mkdir dir="${dest.dir}" />
           <mkdir dir="${dest.dir}/${war.name}"/>
           <mkdir dir="${dest.dir}/${war.name}/WEB-INF"/>
           <mkdir dir="${dest.dir}/${war.name}/WEB-INF/classes"/>
           <delete dir="${client.dir}" />
           <mkdir dir="${client.dir}"/>
        </target>

	<target name="build-service" depends="prepare">
	    <apt    fork="true"
	            destdir="${dest.dir}/${war.name}/WEB-INF/classes"
	            sourcedestdir="${dest.dir}/${war.name}/WEB-INF/classes"
	            sourcepath="${src.dir}">
	        <classpath>
	            <path refid="jboss.classpath"/>
	            <pathelement location="${basedir}/src"/>
	        </classpath>
	        <source dir="${basedir}">
	            <include name="src/**/*.java"/>
	        </source>
	    </apt>
	    <!-- copy handlers descriptor file -->
	    <copy todir="${dest.dir}/${war.name}/WEB-INF">
	        <fileset dir="${basedir}/src">
	            <include name="**/*.xml"/>
	        </fileset>
	    </copy>
	</target>

        <target name="deploy" depends="build-service">
             <copy todir="${jboss.profile}/deploy">
                  <fileset dir="./build"/>
             </copy>
        </target>

        <target name="post-deploy" depends="deploy">
            <echo message="*******************  NOTE  *********************" />
            <echo message="WebService deployed Successfully. As the Basic Authentication is Enabled for this webservice"/>
            <echo message="So Access the WSDL in following format from Browser"/>
            <echo message="http://kermit:thefrog@localhost:8080/UsernameTokenService?wsdl" />
            <echo message="Syntax: " />
            <echo message="http://Username:Password@localhost:8080/UsernameTokenService?wsdl" />
            <echo message="and then store it in your file system with following name:" />
            <echo message="${client.src.dir}/META-INF/wsdl/UsernameTokenService.wsdl "/>
            <echo message="And then run the ' ant client' To generate client artifacts" />
            <echo message="************************************************" />
        </target>

        <target name="client" >
            <delete dir="${client.dir}" />
            <mkdir dir="${client.dir}"/>
            <mkdir dir="${client.dir}/META-INF"/>
            <wsimport destdir="${client.dir}"
                      wsdl="${client.src.dir}/META-INF/wsdl/UsernameTokenService.wsdl"
                      package="client.wssecurity"
                      keep="true">
            </wsimport>

            <javac srcdir="${client.src.dir}" destdir="${client.dir}"  includes="SimpleUsernameTestCase.java" classpathref="jboss.client.classpath"/>
            <jar jarfile="${client.dir}/${client.jar.name}" basedir="${client.dir}" compress="true" >
                <metainf dir="${client.src.dir}/META-INF">
                    <filename name="**/*"/>
                </metainf>
            </jar>
        </target>

        <target name="run" >
            <java classname="client.wssecurity.SimpleUsernameTestCase" fork="true"  >
	        <classpath>
	            <pathelement location="${client.dir}/${client.jar.name}"/>
	            <path refid="jboss.client.classpath"/>
	        </classpath>
                <jvmarg line="-Djava.endorsed.dirs=/home/userone/JBoss_All/jboss-AS6/jboss-as/lib/endorsed" />
            </java>
        </target>
</project>

NOTE:

If you will not set fork=”true” in the client’s run target (as mentioned in line-150 of above script) then the jvmargs wil be ignored and the “Dava.endorsed.dirs” will not be honored so you will see the following kind of exception while running your client application. So you must set the “-Djava.endorsed.dirs” to tell the client to use the JBoss’s JAXWS implementation over the JVM’s.

      javax.xml.ws.WebServiceException: java.lang.UnsupportedOperationException: setProperty must be overridden by all subclasses of SOAPMessage
      	at org.jboss.ws.core.jaxws.client.ClientImpl.handleRemoteException(ClientImpl.java:310)
      	at org.jboss.ws.core.jaxws.client.ClientImpl.invoke(ClientImpl.java:243)
      	at org.jboss.ws.core.jaxws.client.ClientProxy.invoke(ClientProxy.java:171)
      	at org.jboss.ws.core.jaxws.client.ClientProxy.invoke(ClientProxy.java:157)
      	at $Proxy7.getUsernameToken(Unknown Source)


Step10).
Now open a command/shell prompt and make sure that ANT and JAVA path is set properly init like following and then run the ant to build and deploy the webservice:

export PATH=/home/userone/MyJdks/jdk1.6.0_21/bin:/home/userone/JBoss_All/jboss-AS6/jboss-as/bin:/home/userone/org.apache.ant_1.6.5/bin:$PATH

[userone@localhost UserNameToken_WebService]$ ant
Buildfile: build.xml

prepare:
   [delete] Deleting directory /home/userone/Downloads/UserNameToken_WebService/build
    [mkdir] Created dir: /home/userone/Downloads/UserNameToken_WebService/build
    [mkdir] Created dir: /home/userone/Downloads/UserNameToken_WebService/build/UsernameTokenService.war
    [mkdir] Created dir: /home/userone/Downloads/UserNameToken_WebService/build/UsernameTokenService.war/WEB-INF
    [mkdir] Created dir: /home/userone/Downloads/UserNameToken_WebService/build/UsernameTokenService.war/WEB-INF/classes
   [delete] Deleting directory /home/userone/Downloads/UserNameToken_WebService/clientStuff
    [mkdir] Created dir: /home/userone/Downloads/UserNameToken_WebService/clientStuff

build-service:
      [apt] warning: Annotation types without processors: [org.jboss.ws.annotation.EndpointConfig, javax.annotation.Resource]
      [apt] 1 warning
     [copy] Copying 2 files to /home/userone/Downloads/UserNameToken_WebService/build/UsernameTokenService.war/WEB-INF

deploy:
     [copy] Copying 4 files to /home/userone/JBoss_All/jboss-AS6/jboss-as/server/default_Audit/deploy

post-deploy:
     [echo] *******************  NOTE  *********************
     [echo] WebService deployed Successfully. As the Basic Authentication is Enabled for this webservice
     [echo] So Access the WSDL in following format from Browser
     [echo] http://kermit:thefrog@localhost:8080/UsernameTokenService?wsdl
     [echo] Syntax:
     [echo] http://Username:Password@localhost:8080/UsernameTokenService?wsdl
     [echo] and then store it in your file system with following name:
     [echo] /home/userone/Downloads/UserNameToken_WebService/clientSrc/META-INF/wsdl/UsernameTokenService.wsdl
     [echo] And then run the ' ant client' To generate client artifacts
     [echo] ************************************************

BUILD SUCCESSFUL
Total time: 3 seconds

Step11). WebService deployed Successfully. As the Basic Authentication is Enabled for this webservice, So Access the WSDL in following format from Web Browser as following :
http://kermit:thefrog@localhost:8080/UsernameTokenService?wsdl

Syntax:
http://Username:Password@localhost:8080/UsernameTokenService?wsdl
And then save it in your file system with following name: “/home/userone/Downloads/UserNameToken_WebService/clientSrc/META-INF/wsdl/UsernameTokenService.wsdl” And then run the ‘ant client’ To generate client artifacts.

[userone@localhost UserNameToken_WebService]$ ant client
Buildfile: build.xml

client:
   [delete] Deleting directory /home/userone/UserNameToken_WebService/clientStuff
    [mkdir] Created dir: /home/userone/UserNameToken_WebService/clientStuff
    [mkdir] Created dir: /home/userone/UserNameToken_WebService/clientStuff/META-INF
 [wsimport] Consider using <depends>/<produces> so that wsimport won't do unnecessary compilation
 [wsimport] parsing WSDL...

 [wsimport] generating code...

 [wsimport] compiling code...

    [javac] Compiling 1 source file to /home/userone/UserNameToken_WebService/clientStuff
      [jar] Building jar: /home/userone/UserNameToken_WebService/clientStuff/usernameTokenClient.jar

BUILD SUCCESSFUL
Total time: 5 seconds
[userone@localhost UserNameToken_WebService]$

Step12). Now you can run the ant script to execute the client program:

[userone@localhost UserNameToken_WebService]$ ant run
Buildfile: build.xml

run:
      WSDL URL: jar:file:/home/userone/UserNameToken_WebService/clientStuff/usernameTokenClient.jar!/META-INF/wsdl/UsernameTokenService.wsdl
      Security URL: jar:file:/home/userone/UserNameToken_WebService/clientStuff/usernameTokenClient.jar!/META-INF/jboss-wsse-client.xml
       org.jboss.ws.core.StubExt loaded ..file:/home/userone/JBoss_All/jboss-AS6/jboss-as/client/jbossws-native-core.jar
      log4j:WARN No appenders could be found for logger (org.jboss.ws.metadata.builder.jaxws.JAXWSWebServiceMetaDataBuilder).
      log4j:WARN Please initialize the log4j system properly.

      	2

      	3

      	4

      	5 Call Successfuly Made.

BUILD SUCCESSFUL
Total time: 3 seconds

Step13). If you want to see how the SOAP messages are being sent and received then please add the following category in your “$PROFILE/conf/jboss-log4j.xml” file so that the SOAP messages will start appearing in the server.log file.

   <!-- Enable JBossWS message tracing -->
   <category name="org.jboss.ws.core.MessageTrace">
     <priority value="TRACE"/>
   </category>

Step14). Once you will enable the above category in jboss-log4j.xml file then in your server log you will be able to see the following kind of SOAP messages with the username tokens:

15:21:38,585 TRACE [org.jboss.ws.core.MessageTrace] (http-127.0.0.1-8080-1) Incoming Request Message
<env:Envelope xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'>
 <env:Header>
  <wsse:Security env:mustUnderstand='1' xmlns:ds='http://www.w3.org/2000/09/xmldsig#' xmlns:wsse='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd' xmlns:wsu='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd'>
   <wsse:UsernameToken wsu:Id='token-1-1317030698447-695206801'>
    <wsse:Username>kermit</wsse:Username>
    <wsse:Password Type='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText'>thefrog</wsse:Password>
   </wsse:UsernameToken>
  </wsse:Security>
 </env:Header>
 <env:Body>
  <ns1:getUsernameToken xmlns:ns1='http://wssecurity'/>
 </env:Body>
</env:Envelope>

15:21:38,590 INFO  [STDOUT] (http-127.0.0.1-8080-1)
	[WebService- UsernameBean] getUsernameToken: kermit
15:21:38,592 TRACE [org.jboss.ws.core.MessageTrace] (http-127.0.0.1-8080-1) Outgoing Response Message
<env:Envelope xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'>
 <env:Header/>
 <env:Body>
  <ns1:getUsernameTokenResponse xmlns:ns1='http://wssecurity'>
   <return>Hello User: kermit</return>
  </ns1:getUsernameTokenResponse>
 </env:Body>
</env:Envelope>

Step15). If you even want to see the Http Request response details (like http headers/cookies) in the server STDOUT then in that case you can UNCOMMENT the following section in “$PROFILE/deploy/jbossweb.sar/server.xml” file

            <!--
            <Valve className="org.apache.catalina.valves.RequestDumperValve" />
            -->

Step16). Restart you JBoss AS6 profile and then you will start seeing following kind of Http Request Tracing in your server’s STDOUT while making an application call:

15:37:47,292 INFO  [ServerImpl] JBoss (Microcontainer) [5.1.0 (build: SVNTag=JBPAPP_5_1_0 date=201009150028)] Started in 25s:758ms
15:37:57,179 INFO  [[localhost]] REQUEST URI       =/UsernameTokenService
15:37:57,185 INFO  [[localhost]]           authType=null
15:37:57,187 INFO  [[localhost]]  characterEncoding=UTF-8
15:37:57,187 INFO  [[localhost]]      contentLength=-1
15:37:57,187 INFO  [[localhost]]        contentType=text/xml; charset=UTF-8
15:37:57,188 INFO  [[localhost]]        contextPath=/UsernameTokenService
15:37:57,191 INFO  [[localhost]]             header=authorization=Basic a2VybWl0OnRoZWZyb2c=
15:37:57,191 INFO  [[localhost]]             header=soapaction=""
15:37:57,191 INFO  [[localhost]]             header=content-type=text/xml; charset=UTF-8
15:37:57,191 INFO  [[localhost]]             header=jboss-remoting-version=22
15:37:57,191 INFO  [[localhost]]             header=user-agent=JBossRemoting - 2.5.3.SP1 (Flounder)
15:37:57,191 INFO  [[localhost]]             header=remotingcontenttype=remotingContentTypeNonString
15:37:57,191 INFO  [[localhost]]             header=host=127.0.0.1:8080
15:37:57,191 INFO  [[localhost]]             header=accept=text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
15:37:57,191 INFO  [[localhost]]             header=connection=keep-alive
15:37:57,191 INFO  [[localhost]]             header=transfer-encoding=chunked
15:37:57,191 INFO  [[localhost]]             locale=en_US
15:37:57,191 INFO  [[localhost]]             method=POST
15:37:57,193 INFO  [[localhost]]           pathInfo=/
15:37:57,193 INFO  [[localhost]]           protocol=HTTP/1.1
15:37:57,193 INFO  [[localhost]]        queryString=null
15:37:57,194 INFO  [[localhost]]         remoteAddr=127.0.0.1
15:37:57,194 INFO  [[localhost]]         remoteHost=127.0.0.1
15:37:57,194 INFO  [[localhost]]         remoteUser=null
15:37:57,194 INFO  [[localhost]] requestedSessionId=null
15:37:57,194 INFO  [[localhost]]             scheme=http
15:37:57,194 INFO  [[localhost]]         serverName=127.0.0.1
15:37:57,194 INFO  [[localhost]]         serverPort=8080
15:37:57,194 INFO  [[localhost]]        servletPath=
15:37:57,194 INFO  [[localhost]]           isSecure=false
15:37:57,194 INFO  [[localhost]] ---------------------------------------------------------------
15:37:57,425 INFO  [STDOUT]
	[WebService- UsernameBean] getUsernameToken: kermit
15:37:57,439 INFO  [[localhost]] ---------------------------------------------------------------
15:37:57,440 INFO  [[localhost]]           authType=BASIC
15:37:57,440 INFO  [[localhost]]      contentLength=-1
15:37:57,440 INFO  [[localhost]]        contentType=text/xml;charset=UTF-8
15:37:57,440 INFO  [[localhost]]             header=X-Powered-By=Servlet 2.5; JBoss-5.0/JBossWeb-2.1
15:37:57,440 INFO  [[localhost]]             header=Content-Type=text/xml;charset=UTF-8
15:37:57,440 INFO  [[localhost]]             header=Transfer-Encoding=chunked
15:37:57,440 INFO  [[localhost]]             header=Date=Mon, 26 Sep 2011 10:07:57 GMT
15:37:57,440 INFO  [[localhost]]            message=null
15:37:57,440 INFO  [[localhost]]         remoteUser=kermit
15:37:57,440 INFO  [[localhost]]             status=200
15:37:57,440 INFO  [[localhost]] ===============================================================

.
.
Thanks
Middleware Magic Team


Listing & Deleting Messages from JMS Queue using JMX

Hi,

Many times due to different requirement it is desired to list all the Messages present inside the JMS Queue. Also some times it is required to delete all the messages present inside the JMS Queue. jmx-console can be used to perform the same tasks, but most of the time in production environments we disable the jmx-console or admin-console. So in such scenarios we can use the following kind of JMX code to list and if required then delete the Messages present inside the JMS Queue.

In this sample we will be using the default JMS Queue provided by JBoss as “queue/DLQ” but if you want to create your own JMS Queue then you can refer to the following article “How to create a Queue in JBoss ?“. Also we will be using a simple “QueueSend.java” program to send some test messages in the JMS Queue and then with the help of “ManageJMSQueue.java” program we will list the JMS Messages present inside the JMS Queue and if required we will delete them through the same JMX Code.

Step1). Write the Simple “QueueSend.java” program somewhere in your file system to send some JMS Messages to the JMS Queue “queue/DLQ” as following:

import java.io.*;
import java.util.Hashtable;
import javax.jms.JMSException;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class QueueSend
{
	public final static String JNDI_FACTORY="org.jnp.interfaces.NamingContextFactory";
	public final static String JMS_FACTORY="/XAConnectionFactory";
	public final static String QUEUE="/queue/DLQ";
	private QueueConnectionFactory qconFactory;
	private QueueConnection qcon;
	private QueueSession qsession;
	private QueueSender qsender;
	private Queue queue;
	private TextMessage msg;

public void init(Context ctx, String queueName)throws NamingException, JMSException
     {
	qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY);
	qcon = qconFactory.createQueueConnection();
	qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
	queue = (Queue) ctx.lookup(queueName);
	qsender = qsession.createSender(queue);
	msg = qsession.createTextMessage();
	qcon.start();
     }

public void send(String message) throws JMSException
     {
	msg.setText(message);
	qsender.send(msg);
     }

public void close() throws JMSException
     {
	qsender.close();
	qsession.close();
	qcon.close();
     }

public static void main(String[] args) throws Exception {
	if (args.length != 1) {
	System.out.println("Usage: java QueueSend JBossURL");
	System.out.println("Example: java QueueSend localhost:1099");
	return;
	}
	InitialContext ic = getInitialContext(args[0]);
	QueueSend qs = new QueueSend();
	qs.init(ic, QUEUE);
	readAndSend(qs);
	qs.close();
	}

private static void readAndSend(QueueSend qs) throws IOException, JMSException
    {
	String line="Test Message Body with counter = ";
	BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
	boolean readFlag=true;
	System.out.println("ntStart Sending Messages (Enter QUIT to Stop):n");
        int i=1;
	while(readFlag)
	{
	   System.out.print("<Msg_Sender> ");
	   String msg=br.readLine();
	   if(msg.equals("QUIT") || msg.equals("quit"))
	    {
	        qs.send(msg);
        	System.exit(0);
 	    }
        qs.send(msg);
        System.out.println("ttt msg sent: "+i+"t "+msg);
        i++;
        System.out.println();
	}
	br.close();
     }

private static InitialContext getInitialContext(String url) throws NamingException
    {
	Hashtable<String,String> env = new Hashtable<String,String>();
	env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
	env.put(Context.PROVIDER_URL, url);
	return new InitialContext(env);
    }
}

Step2). Now write the “ManageJMSQueue.java” program as following in order to list the messages present inside the JMS Queue “queue/DLQ” and if required delete them through the same code.

import javax.management.*;
import java.io.*;
import java.util.*;
import java.rmi.*;
import javax.naming.*;
import java.io.*;
public class ManageJMSQueue
   {
      private MBeanServerConnection server=null;
      public ManageJMSQueue()
      {
            try{
            Hashtable<String,String> ht=new Hashtable<String,String>();
            ht.put(Context.INITIAL_CONTEXT_FACTORY,"org.jboss.security.jndi.JndiLoginInitialContextFactory");
            ht.put(Context.PROVIDER_URL,"localhost:1099");
            ht.put(Context.SECURITY_PRINCIPAL,"admin");
            ht.put(Context.SECURITY_CREDENTIALS,"admin");
            System.out.println("nt 1- Gotting InitialContext...... ");
            Context ctx = new InitialContext(ht);
            System.out.println("nt 2- Got InitialContext: "+ctx);
            server = (MBeanServerConnection) ctx.lookup("jmx/invoker/RMIAdaptor");
            }
            catch(Exception e)
            {
                System.out.println("nnt Exception inside ManageJMSQueue..."+e);
            }
      }

      public void monitorJMS() throws Exception
      {
           ObjectName objectName=new ObjectName("jboss.messaging.destination:name=DLQ,service=Queue");
           System.out.println("nnServerPeer = "+ (javax.management.ObjectName)server.getAttribute(objectName, new String("ServerPeer")));
           System.out.println("QueueName = "+ (String)server.getAttribute(new ObjectName("jboss.messaging.destination:name=DLQ,service=Queue"), new String("Name")));
           System.out.println("JNDI Name = "+ (String)server.getAttribute(new ObjectName("jboss.messaging.destination:name=DLQ,service=Queue"), new String("JNDIName")));
           System.out.println("FullSize = "+ (Integer)server.getAttribute(new ObjectName("jboss.messaging.destination:name=DLQ,service=Queue"), new String("FullSize")));
      }

     public void listAllJMS_Messages() throws Exception
      {
           ObjectName objectName=new ObjectName("jboss.messaging.destination:name=DLQ,service=Queue");
           List<org.jboss.jms.message.JBossTextMessage> messages=(List<org.jboss.jms.message.JBossTextMessage>)server.invoke(objectName, "listAllMessages" , null, null);
           int count=0;
           for(org.jboss.jms.message.JBossTextMessage msg : messages)
                    System.out.println((++count)+"t"+msg.getText());
      }

     public void removeAllJMS_Messages() throws Exception
      {
           String queueName=(String)server.getAttribute(new ObjectName("jboss.messaging.destination:name=DLQ,service=Queue"), new String("Name"));
           System.out.println("nt Removing all JMS Messages from Queue: "+queueName);
           server.invoke(new ObjectName("jboss.messaging.destination:name=DLQ,service=Queue"), "removeAllMessages" , null, null);
           System.out.println("nt All the Messages are removed from JMS Queue: "+queueName);
      }

     public static void main(String ar[]) throws Exception
       {
            ManageJMSQueue ref=new ManageJMSQueue();
            ref.monitorJMS();
            System.out.println("nt Following Messages Are present inside the JMS Queue:");
            ref.listAllJMS_Messages();
            BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
            System.out.print("nn Please Specify (yes/no) to delete all the messages from JMS Queue ? ");
            String answer="";
            if((answer=br.readLine()).equals("yes"))
                             ref.removeAllJMS_Messages();
            br.close();
       }
  }

Step3). Compile and then run the “QueueSend.java” program as following and then send some messages to the JMS Queue:

javac QueueSend.java
java QueueSend localhost:1099
	Start Sending Messages (Enter QUIT to Stop):

<Msg_Sender> TestMessageOne
			 msg sent: 1	 TestMessageOne

<Msg_Sender> TestMessageTwo
			 msg sent: 2	 TestMessageTwo

<Msg_Sender> TestMessageThree
			 msg sent: 3	 TestMessageThree

<Msg_Sender> quit

Step4). After sending some Messages to the JMS Queue “queue/DLQ” Compile and then run the “ManageJMSQueue” program as following to list the messages present inside the JMS Queue:

javac ManageJMSQueue.java
java ManageJMSQueue localhost:1099

	 1- Gotting InitialContext......
	 2- Got InitialContext: javax.naming.InitialContext@74341960

ServerPeer = jboss.messaging:service=ServerPeer
QueueName = DLQ
JNDI Name = /queue/DLQ
FullSize = 200000

	 Following Messages Are present inside the JMS Queue:
1	TestMessageOne
2	TestMessageTwo
3	TestMessageThree
4	quit

 Please Specify (yes/no) toi delete all the messages from JMS Queue ? yes
	 Removing all JMS Messages from Queue: DLQ
	 All the Messages are removed from JMS Queue: DLQ

.
.
Thanks
Middleware Magic Team


Generating HeapDump while running JBoss as a Windows Service

Hi,

This article is very important in case of JBoss running as a Windows Service, Because if we run any Server JBoss or any other application server as a Windows Service then NONE of the JVM utilities like “jmap”, “jconsole” , “jps” or “VisualVM”… etc will work. So it becomes very difficult to collect the Thread Dump or Heap Dump of the Running Service.

We wrote an article based on JMX to collect the JVM’s memory related statistics using JMX code “Monitoring Heap & NonHeap Memory of JBoss using MBean code. Here we are extending the same program to make the JMX program to even collect the HeapDump whenever we want.

To connect to the actual JConsole remotely also we need to provide the following JAVA_OPTS inside our “$JBOSS_HOME/bin/run.bat” (run.conf.bat) file the connection url format should be:

service:jmx:rmi:///jndi/rmi://"+hostname+":"+port+"/jmxrmi

Step1). Edit the “%JBOSS_HOME%/bin/run.conf.bat” or “%JBOSS_HOME%/bin/run.bat” (Server StartScript configuration file) and then set the following JAVA_OPTS there.

set JAVA_OPTS="%JAVA_OPTS% -Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.port=4545 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djavax.management.builder.initial=org.jboss.system.server.jmx.MBeanServerBuilderImpl -Djboss.platform.mbeanserver"

Make sure that the 4545 is not being used by any other process. Or define any other port in above parameter which is free.

Step2). Now from any other box or from the same Box you can run the Following JMX code to generate the HeapDump of the JVM process:
“GenerateHeapDump.java”

import java.util.Hashtable;
import java.io.*;
import javax.management.MBeanServerConnection;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import javax.naming.Context;
import java.lang.management.MemoryMXBean;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import javax.management.*;
import javax.management.openmbean.CompositeDataSupport;

public class GenerateHeapDump
{
	private static MBeanServerConnection connection;
	private static JMXConnector connector;
	public static void Connection(String hostname, String port) throws IOException
	{
		Integer portInteger = Integer.valueOf(port);
		Hashtable h = new Hashtable();
		JMXServiceURL address = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://"+hostname+":"+port+"/jmxrmi");
		connector = JMXConnectorFactory.connect(address,null);
		connection = connector.getMBeanServerConnection();
		System.out.println("GOT THE MBeanServerConnection---SUCCESSFULLY");
	}

	private static void doGarbageCollection() throws Exception
	{
		ObjectName memoryMXBean=new ObjectName("java.lang:type=Memory");
		connection.invoke(memoryMXBean,"gc", null, null);
		System.out.println("nnt------Garbage Collection Done Successfully-----");
	}

	private static void getHeapDump(String fileName) throws Exception
	{
		ObjectName memoryMXBean=new ObjectName("com.sun.management:type=HotSpotDiagnostic");
		Object[] params = new Object[] { "C:/WindowsService_Script/"+fileName, Boolean.TRUE };
		String[] signature = new String[] { String.class.getName(), boolean.class.getName() };
		Object result = connection.invoke(memoryMXBean, "dumpHeap" , params, signature);
		System.out.println("nt Heap Dump Generated to " +fileName);
	}

	public static void main(String[] args) throws Exception
	{
	String hostname = args[0];
	String port = args[1];
	Connection(hostname, port);
	System.out.println("nt----------Generating Heap Dump---------");
	getHeapDump("HeapDump.hprof");
	connector.close();
	}
}

Step3). Run your JBoss Windows Service and then compile and run your Program to generate the HeapDump

C:WindowsService_Script>set PATH=c:jdk160_05bin;%PATH%;
C:WindowsService_Script>javac GenerateHeapDump.java

C:WindowsService_Script>java GenerateHeapDump 10.10.10.10 4545
GOT THE MBeanServerConnection---SUCCESSFULLY

        ----------Generating Heap Dump---------
         Heap Dump Generated to HeapDump.hpro

NOTE: you will find the generated HeapDump in the "C:/WindowsService_Script/" directory in the Box where the JBoss is running as a Service which is defined in line -39 in above code.

.
.
Thanks
Middleware Magic Team


Copyright © 2010-2012 Middleware Magic. All rights reserved. |