magrokosmos

Tuesday, September 05, 2006

New bug in jconsole of Mustang

as stated here there's a new bug in jconsole with serviceUrls. This works with jdk 5 but not with beta 2 of jdk 6.
The bug will be filed under bug id 6467247.

Monday, September 04, 2006

Moved to javakaffee.de

I just moved to my domain javakaffee.de and created a new blog using wordpress. The latest articles like JMXtend your Spring application…, the one about heap dump analysis and so forth i have all moved.

Thursday, August 24, 2006

JMXtend your Spring application...

...with both own annotated beans and Hibernates StatisticsService.

I just managed to export an annotation based (Spring managed) bean to JMX. This is fairly simple and can even be done using the "autodetection" mechanism of springs MBeanExporter.

The following snipplet shows the relevant part of the applicationContext.xml:
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="assembler">
<!-- will create management interface using annotation metadata -->
<bean class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
<property name="attributeSource" ref="jmxAttributeSource"/>
</bean>
</property>
<property name="namingStrategy">
<!-- will pick up ObjectName from annotation -->
<bean id="namingStrategy"
class="org.springframework.jmx.export.naming.MetadataNamingStrategy">
<property name="attributeSource" ref="jmxAttributeSource"/>
</bean>
</property>
<property name="autodetect" value="true"/>
</bean>

<bean id="jmxAttributeSource"
class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/>

The java class is defined as follows:
@ManagedResource(objectName="org.company.project:name=MailService", description="Mail Service",
log=true, logFile="jmx.log", currencyTimeLimit=15, persistPolicy="OnUpdate",
persistPeriod=200, persistLocation="foo", persistName="bar")
public final class MailServiceImpl {
...
@ManagedAttribute(description="Get the number of queued mail deliveries.")
public int getCountQueuedEmails() {
return _queue.size();
}
}

This is everything one has to do to expose a Spring bean via JMX.

If you want to check if it's working just run jconsole (it's distributed with Suns jvm) and connect to the Bootstrap process.
But stop - if you're running tomcat, you should add to the catalina.sh|bat the following catalina (java) options (when you're using startup/shutdown scripts, export the variable in startup.sh|bat):
CATALINA_OPTS="-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=8099
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false"

(You can also just use the JAVA_OPTS variable)

Now lets proceed and export the StatisticsService of Hibernate to JMX (also using the MBeanExporter). For this it's necessary to turn the MBeanExporters autodetection off, otherwise he would complain that the StatisticsService has no ManagedResource annotation. The formerly autodetected bean (mailService) in consequence must be declared via the beans property. After this has been changed, a new exporter (using method name based assembly) for the StatisticsService can be declared.

Then the spring configuration is the following:
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="assembler">
<!-- will create management interface using annotation metadata -->
<bean class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
<property name="attributeSource" ref="jmxAttributeSource"/>
</bean>
</property>
<property name="namingStrategy">
<!-- will pick up ObjectName from annotation -->
<bean id="namingStrategy"
class="org.springframework.jmx.export.naming.MetadataNamingStrategy">
<property name="attributeSource" ref="jmxAttributeSource"/>
</bean>
</property>
<property name="autodetect" value="false"/>
<property name="beans">
<map>
<entry key="foo1">
<ref local="mailService" />
</entry>
</map>
</property>
</bean>

<bean id="jmxAttributeSource"
class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/>

<bean id="methodNameBasedExporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="beans">
<map>
<entry key="org.hibernate:name=StatisticsService">
<bean class="org.hibernate.jmx.StatisticsService">
<property name="sessionFactory" ref="sessionFactory"/>
<property name="statisticsEnabled">
<value>true</value>
</property>
</bean>
</entry>
</map>
</property>
<property name="assembler">
<bean class="org.springframework.jmx.export.assembler.MethodNameBasedMBeanInfoAssembler">
<property name="methodMappings">
<props>
<prop key="bean:name=StatisticsService" />
</props>
</property>
</bean>
</property>
</bean>

Tuesday, August 22, 2006

freenigma beta phase started

Finally, the public beta phase of the freenigma service started, after the launch was announced at heise.de some days ago.
The freenigma service allows you to send encrypted emails from your favorite webmail provider, so that your privacy and business secrets will be protected again, and will not be stored as plaintext on the providers servers.
You can register online and apply for an invitation to the freenigma service, or just ask here (write a comment) so that i can invite you.
The official announcement concerning the start of the beta phase you find here at the freiheit.com blog.

Heap Dump Analysis

Until now i used an IBM jdk to track down memory problems. The IBM jdks allow to create heap dumps on OutOfMemoryErrors (or with kill -3) and afterwards analyse them with the HeapAnalyzer. More information on this you find in the IBM Diagnostics Guide. There seemed to be nearly no impact on performance, why i could use this also in production environments (for a short time).

Although, in some cases it's not possible to use an IBM jdk (e.g. because some sun specific implementation is required).

Now it seems to be possible to do something similar with sun jdks: in this posting on TSS i read that you can start your jvm with -XX:+HeapDumpOnOutOfMemoryError (if it's >= 1.4.2_12 or 1.5.0_06). The produced heap dump afterwards you would analyse with HAT (Heap Analysis Tool, legacy), or the newer jhat (included in Mustang).

For now i didn't test this new feature of the sun jvm, i'll post an update when i've done this.

Some links on jhat and the OQL (Object Query Language):
What's in my Java heap?
Querying Java heap with OQL
Permanent generation analysis with OQL

References:
Alan Bateman: HeapDumpOnOutOfMemoryError option in 5.0u7 and 1.4.2_12.

Tuesday, July 04, 2006

JSF/Acegi authentication with a backing bean

STOP! This posting (the whole blog) is outdated, i moved to http://www.javakaffee.de/blog/. This posting you find now at http://www.javakaffee.de/blog/2006/07/04/jsfacegi-authentication-with-a-backing-bean/

Thanx to this blog post i managed to integrate Acegi 1.0.1 with JSF. Some minor modifications were necessary, because in this version of Acegi some things have changed.

The basic idea of this approach is to use a JSF backing bean that is responsible for authentication (that processes the "login" request from the user). This allows you not only to send the user to a success/error page, but you are also able to send him to a custom page if some condition is met.

The backing bean looks like the following:


package com.freiheit;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.acegisecurity.Authentication;
import org.acegisecurity.AuthenticationManager;
import org.acegisecurity.context.HttpSessionContextIntegrationFilter;
import org.acegisecurity.context.SecurityContext;
import org.acegisecurity.context.SecurityContextHolder;
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.acegisecurity.ui.WebAuthenticationDetails;
import org.acegisecurity.ui.webapp.AuthenticationProcessingFilter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Required;

public final class AuthenticationController {

private static final Log LOG = LogFactory.getLog( AuthenticationController.class );

private String _username;
private String _password;

// injected properties
private AuthenticationManager _authenticationManager;

public String getPassword() {
return _password;
}

public void setPassword( String password ) {
_password = password;
}

public String getUsername() {
return _username;
}

public void setUsername( String userName ) {
_username = userName;
}

@SuppressWarnings("unchecked")
public String authenticate() {
String outcome = "failure";

try {
final String userName = getUsername();
final String password = getPassword();
final UsernamePasswordAuthenticationToken authReq = new UsernamePasswordAuthenticationToken(
userName, password );

final HttpServletRequest request = getRequest();
authReq.setDetails( new WebAuthenticationDetails( request ) );

final HttpSession session = request.getSession();
session.setAttribute(
AuthenticationProcessingFilter.ACEGI_SECURITY_LAST_USERNAME_KEY,
userName );

/* perform authentication
*/
final Authentication auth = getAuthenticationManager().authenticate( authReq );

/* initialize the security context.
*/
final SecurityContext secCtx = SecurityContextHolder.getContext();
secCtx.setAuthentication( auth );
session.setAttribute( HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY, secCtx );

outcome = "success";

} catch ( Exception e ) {
outcome = "failure";
FacesContext.getCurrentInstance().addMessage( null, new FacesMessage( e.getMessage() ) );
}

return outcome;
}

public void logout( ActionEvent e ) {

final HttpServletRequest request = getRequest();
request.getSession( false ).removeAttribute( HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY );

/* simulate the SecurityContextLogoutHandler
*/
SecurityContextHolder.clearContext();

request.getSession( false ).invalidate();
}

private HttpServletRequest getRequest() {
return (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
}

public AuthenticationManager getAuthenticationManager() {
return _authenticationManager;
}

@Required
public void setAuthenticationManager(
AuthenticationManager authenticationManager ) {
_authenticationManager = authenticationManager;
}

}


The spring configuration (applicationContext.xml) has the following entries:


<bean id="acegiFilterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
<property name="filterInvocationDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/**=httpSessionContextIntegrationFilter,securityRequestFilter,exceptionTranslationFilter,filterSecurityInterceptor
</value>
</property>
<!--
/**=httpSessionContextIntegrationFilter,requestWrapper,filterSecurityInterceptor
-->
</bean>

<bean id="httpSessionContextIntegrationFilter" class="org.acegisecurity.context.HttpSessionContextIntegrationFilter">
<property name="context">
<value>org.acegisecurity.context.SecurityContextImpl</value>
</property>
</bean>

<bean id="securityRequestFilter" class="org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter" />

<bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
<property name="authenticationEntryPoint">
<bean class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
<property name="loginFormUrl">
<value>/login.jsf</value>
</property>
<property name="forceHttps"><value>false</value></property>
</bean>
</property>
<property name="accessDeniedHandler">
<bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl">
<property name="errorPage">
<value>/accessDenied.jsf</value>
</property>
</bean>
</property>
</bean>

<bean id="filterSecurityInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
<property name="accessDecisionManager">
<bean class="org.acegisecurity.vote.UnanimousBased">
<property name="decisionVoters">
<list>
<bean class="org.acegisecurity.vote.RoleVoter">
<!-- Reset the role prefix to "", default is ROLE_ -->
<property name="rolePrefix">
<value></value>
</property>
</bean>
</list>
</property>
</bean>
</property>
<property name="objectDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/pages/company/**=/permissions/permission1
/pages/**=/permissions/permission01
</value>
</property>
</bean>

<bean id="authenticationManager"
class="org.acegisecurity.providers.ProviderManager">
<property name="providers">
<list>
<ref local="daoAuthenticationProvider" />
</list>
</property>
</bean>

<bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
<property name="userDetailsService">
<bean class="org.acegisecurity.userdetails.memory.InMemoryDaoImpl">
<property name="userMap">
<value>
mgrotzke=test123,/permissions/permission1,/permissions/permission01
skaiser=test123,/permissions/permission01
</value>
</property>
</bean>
</property>
</bean>

<bean id="authenticationController" class="com.freiheit.AuthenticationController">
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
</bean>


The authenticationController bean is the backing bean (see above) that is called from the (jsp/facelets) page. It can be defined in the spring applicationContext.xml because the faces-config contains an entry for springs DelegatingVariableResolver:


<application>
<variable-resolver>
org.springframework.web.jsf.DelegatingVariableResolver
</variable-resolver>
</application>


The web.xml has the following filter entry for acegi:


<filter>
<filter-name>Acegi Filter Chain Proxy</filter-name>
<filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
<init-param>
<param-name>targetBean</param-name>
<param-value>acegiFilterChainProxy</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>Acegi Filter Chain Proxy</filter-name>
<servlet-name>Faces Servlet</servlet-name>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>


The faces-config.xml contains the following navigation-rules for login and logout:

<navigation-rule>
<from-view-id>/login.xhtml</from-view-id>
<navigation-case>
<from-action>#{authenticationController.authenticate}</from-action>
<from-outcome>success</from-outcome>
<to-view-id>/pages/index.xhtml</to-view-id>
<redirect/>
</navigation-case>
<navigation-case>
<from-action>#{authenticationController.authenticate}</from-action>
<from-outcome>failure</from-outcome>
<to-view-id>/login.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>*</from-view-id>
<navigation-case>
<from-action>logout</from-action>
<to-view-id>/login.xhtml</to-view-id>
<redirect/>
</navigation-case>
</navigation-rule>


The login page using facelets essentially has the following content:

<form jsfc="h:form" id="loginForm">
Username: <input jsfc="h:inputText" id="inputUsername" value="#{authenticationController.username}" /><br/>
Password: <input jsfc="h:inputSecret" value="#{authenticationController.password}" /><br/>
<input jsfc="h:commandButton" action="#{authenticationController.authenticate}"
value="Login" />
</form>


The logout button should be defined in an overall template, and would look like the following:

<a href="#" jsfc="h:commandLink" action="logout"
actionListener="#{authenticationController.logout}">#{msgs.logout}</a>

Sunday, July 02, 2006

Finally, i have a blog, too. And that only because i wanted to comment some blog entry.
This is my first entry, and to be honest, it's only for testing. Nothing will be said here - really.