Posts Tagged ‘jboss’

Secure JBoss JMX Console

Since JBoss can now be installed from a zip file it comes with a default unsecured jmx-console. This is unacceptable for production so here is the method to secure the jmx-console using http authentication (applies to JBoss 4.2.2.GA).

1. Edit jboss/server/default/deploy/jmx-console.war/WEB-INF/web.xml and uncomment the security-constraint element:

   <security-constraint>
     <web-resource-collection>
       <web-resource-name>HtmlAdaptor</web-resource-name>
       <description>An example security config that only allows users with the
         role JBossAdmin to access the HTML JMX console web application
       </description>
       <url-pattern>/*</url-pattern>
       <http-method>GET</http-method>
       <http-method>POST</http-method>
     </web-resource-collection>
     <auth-constraint>
       <role-name>JBossAdmin</role-name>
     </auth-constraint>
   </security-constraint>

2. Edit jboss/server/default/deploy/jmx-console.war/WEB-INF/web.xml and uncomment the security-domain element:

<security-domain>java:/jaas/jmx-console</security-domain>

3. Edit jboss/server/default/conf/login-config.xml and make sure that you have the definition of the jmx-console authentication-policy

<application-policy name = "jmx-console">
       <authentication>
          <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule"
             flag = "required">
           <module-option name="usersProperties">props/jmx-console-users.properties</module-option>
           <module-option name="rolesProperties">props/jmx-console-roles.properties</module-option>
          </login-module>
       </authentication>
</application-policy>

4. Edit the files jboss/server/default/conf/props/jmx-console-users.properties and jboss/server/default/conf/props/jmx-console-roles.properties to edit your users.

Another way to use Quartz in JBoss

I was explaining here how to create a Quartz job using the standard Quartz-ra service which comes bundled with JBoss. The method is rather limited, or I was not able to find the proper documentation on how to register new jobs on the fly. This is why in this post I will show how to access the quartz scheduler directly. (more…)

Creating a Quartz job

In new versions of JBoss (such the 4.0.5 which I am using) there is a quartz-ra.sar service which should allow me to define some a job with a cron like specification.

Searching the forums and the jboss site I was able to put together quickly an example:

import org.jboss.annotation.ejb.ResourceAdapter;import org.jboss.logging.Logger;import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;

import javax.ejb.MessageDriven;import javax.ejb.ActivationConfigProperty;

@MessageDriven(activationConfig = { @ActivationConfigProperty(propertyName = "cronTrigger", propertyValue = "0/2 * * * * ?") })

@ResourceAdapter("quartz-ra.rar")

public class Test implements Job {    private static final Logger log = Logger.getLogger(Test.class);

    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {        log.info("executing Test job");    }}

I packed this into a jar and deployed to jboss and was able to see the “executing Test job” message each 2 seconds.

Next step was to externalize the cronTrigger property to an external file such that the property is not hardcodded in the configuration file. This proved to be a very complicated issue since I could find absolutely no example. After 3 hours of searching I was able to put together a working example. Here are the files:

The java file:

import javax.ejb.EJBException;import javax.ejb.MessageDrivenBean;import javax.ejb.MessageDrivenContext;import javax.jms.Message;import javax.jms.MessageListener;

import org.jboss.logging.Logger;import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;

/*MessageDriven(activationConfig = { @ActivationConfigProperty(propertyName = "cronTrigger", propertyValue = "0/2 * * * * ?") }) ResourceAdapter("quartz-ra.rar")*/public class Test implements Job, MessageDrivenBean, MessageListener {	private static final Logger log = Logger.getLogger(Test.class);

	public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {		log.info("executing Test job");	}

	/**	 * @see javax.ejb.MessageDrivenBean#ejbRemove()	 * @throws EJBException	 */	public void ejbRemove() throws EJBException {	}

	/**	 * @see javax.ejb.MessageDrivenBean#setMessageDrivenContext(javax.ejb.MessageDrivenContext)	 * @param context	 * @throws EJBException	 */	public void setMessageDrivenContext(MessageDrivenContext context) throws EJBException {	}

	/**	 * @see javax.jms.MessageListener#onMessage(javax.jms.Message)	 * @param message	 */	public void onMessage(Message message) {	}

	public void ejbCreate() {		log.info("Test job created");	}}

The ejb-jar.xml file:

<?xml version="1.0" encoding="UTF-8"?><ejb-jar 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/ejb-jar_2_1.xsd" version="2.1">    <enterprise-beans>        <message-driven>            <ejb-name>Test</ejb-name>            <ejb-class>Test</ejb-class>            <messaging-type>org.quartz.Job</messaging-type>            <transaction-type>Container</transaction-type>            <activation-config>                <activation-config-property>                    <activation-config-property-name>cronTrigger</activation-config-property-name>                    <activation-config-property-value>                        <![CDATA[0/2 * * * * ?]]>                    </activation-config-property-value>                </activation-config-property>            </activation-config>        </message-driven>    </enterprise-beans></ejb-jar>

The jboss.xml file:

<?xml version="1.0" encoding="UTF-8"?>

<jboss>   <enterprise-beans>      <message-driven>         <ejb-name>Test</ejb-name>         <destination-jndi-name>dummy</destination-jndi-name>         <resource-adapter-name>quartz-ra.rar</resource-adapter-name>      </message-driven>   </enterprise-beans></jboss>

A short list of links which proved usefull:

Does Date() returns localtime?

Getting the correct date and time was always a problem but I could not expect it’s still a problem on today java and OS versions.

Trying to deploy a JBoss on various Linux and JBoss I could not notice that on each system the date in the log was different from the localtime. Initially I thought it’s just a JBoss configuration problem but a simple example shows it’s not:

import java.util.Date;

public class TestDate {	
public static void main(String[] args) {		
System.out.println("Current date is: " + new Date());	
}
}
len@black:$ java TestDateCurrent date is: Tue Jul 03 14:55:03 GMT+02:00 2007

len@black:$ dateTue Jul  3 15:55:13 EEST 2007

len@black:$ java -versionjava version "1.5.0_11"Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_11-b03)Java HotSpot(TM) Server VM (build 1.5.0_11-b03, mixed mode)

After running this on various systems from linux to solaris the results where completely haotic. It took some digging to find a solution for the problem but finally it was rather simple.

java -Duser.timezone=Europe/Bucharest TestDate
java -Duser.timezone=$(cat /etc/timezone) TestDate

Apparently java needs some confirmation of the timezone it’s in in order to display the date correctly.

JBPM Hibernate cache

Applies to: JBPM 3.1.2, JBoss 4.0.5-GA

Everything starts with a beautiful concept but has to pass past those nasty errors. The same applies to this JBPM project, everything was nice, I have seen it running and then I was supposed to take the sources, clean, organize and enhance. Everything ok until now. The only problem is that when deploying the JBPM (sar) service there was this error:

16:09:17,402 ERROR [CommandExecutorThread] org.hibernate.HibernateException: Could not instantiate cache implementation

(more…)

Webapp logging

Applies to: JBoss 4.0.5 GA

Everything started with a web application which worked perfectly inside a Tomcat 5 container and had to be migrated to JBoss. At the first deployment got this error:

14:45:56,496 ERROR [STDERR] log4j:ERROR The class "org.apache.log4j.spi.ErrorHandler" was loaded by 14:45:56,496 ERROR [STDERR] log4j:ERROR [WebappClassLoader  delegate: false  repositories:    /WEB-INF/classes/----------> Parent Classloader:java.net.FactoryURLClassLoader@172bab9] whereas object of type 14:45:56,497 ERROR [STDERR] log4j:ERROR "org.jboss.logging.util.OnlyOnceErrorHandler" was loaded by [org.jboss.system.server.NoAnnotationURLClassLoader@19616c7].14:45:56,542 ERROR [STDERR] log4j:ERROR Could not create an Appender. Reported error follows.14:45:56,542 ERROR [STDERR] java.lang.ClassCastException: org.jboss.logging.appender.DailyRollingFileAppender

After searching the forums for a while I found this link according to which all I had to do is:

export JAVA_OPTS=-Dlog4j.defaultInitOverride=true

This solved indeed the error and I was quite happy to see the application running but I soon realised that in fact this fixed the problem as the error did not occured anymore but the log mechanism did not worked either.

After a lot more search I finally found the JBoss recomandation for this problem: all I had to do is to remove the log4j and commons-logging jars from the war file:

<war warfile.......<lib dir="${lib.dir}">	<include name="*.jar" />	<exclude name="log4j*.jar" />	<exclude name="commons-logging*.jar" /></lib>

JMX invocation with secured console

Applies to: JBoss 4.0.5 GA

As I am working on a rather complex application with a lot of dependancy bounded MBeans I found it necessary to have a small application, in a different JVM, invoke a MBean method for administrative purposes. Even if this sounded easy at the begining it seemed that I had to face 2 problems:

  • JBoss JMX implementation
  • JAAS access to the secured console

Since I both googled and searched JBoss forums without much help I decided, upon succeding, to write this article as it might help someone futher.

The ideea was to get access to a MBean service with the name:

ro.nit.test:service=Test

and to be able to get it’s “Message” attribute and also invoke a remove method called: “printMessage”. The jmx-console was protected with admin/simple

The working code is:

AppCallbackHandler handler = new AppCallbackHandler("admin", "simple".toCharArray());
LoginContext lc = new LoginContext("TestClient", handler);
System.out.println("Created LoginContext");lc.login();

Hashtable env = new Hashtable();
String factory = "org.jnp.interfaces.NamingContextFactory";
env.put(Context.INITIAL_CONTEXT_FACTORY, factory);
String url1 = "jnp://localhost:1099";env.put(Context.PROVIDER_URL, url1);
env.put(Context.SECURITY_CREDENTIALS, "simple");
env.put(Context.SECURITY_PRINCIPAL, "admin");
env.put(Context.SECURITY_PROTOCOL, "testLoginInitialContext");
Context ctx = new InitialContext(env);
MBeanServerConnection mconn = (MBeanServerConnection) ctx.lookup("jmx/invoker/RMIAdaptor");
ObjectName name = new ObjectName("ro.nit.test:service=Test");
Object val = mconn.getAttribute(name, "Message");
System.out.println(name + "\n\tmessage=" + val);
mconn.invoke(name, "printMessage", null, null);

This makes use of the following CallbackHandler implementation:

static class AppCallbackHandler implements CallbackHandler {
private String username;
private char[] password;

public AppCallbackHandler(String username, char[] password) {
	this.username = username;
	this.password = password;
}

public void handle(Callback[] callbacks) throws java.io.IOException, UnsupportedCallbackException {
	for (int i = 0; i < callbacks.length; i++) {
		if (callbacks[i] instanceof NameCallback) {
			NameCallback nc = (NameCallback) callbacks[i];
			nc.setName(username);
		} else if (callbacks[i] instanceof PasswordCallback) {
			PasswordCallback pc = (PasswordCallback) callbacks[i];
			pc.setPassword(password);
		} else {
			throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
		}
	}
}
}

The “auth.conf” file required by JAAS:

other {   
   // jBoss LoginModule   org.jboss.security.ClientLoginModule  required   ;
   // Put your login modules that need jBoss here};

The JVM parameters:

-Djava.security.auth.login.config=file:${path to file}/auth.conf

Links with helped me found the solution:

  • http://www.jboss.com/index.html?module=bb&op=viewtopic&t=95530&view=previous
  • http://www.jboss.org/index.html?module=bb&op=viewtopic&t=84303
  • http://www.jboss.org/index.html?module=bb&op=viewtopic&t=83861

Some errors which I got on the way:

  • Exception in thread “main” java.lang.SecurityException: Failed to authenticate principal=null, securityDomain=jmx-console

The original code (according to JSR160):

JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:8080/jmx-console");
JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
ObjectName stdMBeanName = new ObjectName("ro.nit.test:service=Test");
mbsc.setAttribute(stdMBeanName, new Attribute("Message", "New message set from remote"));
// TODO, will not work with JBOSS since it does not implement the
// JMX properly
// http://www.jboss.com/index.html?module=bb&op=viewtopic&t=95530&view=previous