Sunday, July 29, 2007

JMS with Lingo

Blink It Digg! Dzone

Lingo is one of those little projects what make life a lot easier for a java developer. According to the Lingo people Lingo is a lightweight POJO based remoting and messaging library based on Spring's Remoting which extends it to support JMS. Lingo can support a wide range of message exchange patterns including both synchronous and asynchronous message exchange.

I came across Lingo when I was searching for a really simple JMS solution. Ofcourse I looked into Spring but I didn't like what they offered. In my opinion spring JMS (Message Driven POJO) was still to low level for me. I was searching for a real POJO based solution what handles all the messaging for me, and that is just the thing Lingo does.

This article is focused around how to setup Lingo correctly in your environment. At the bottom you find a link to the source code with a sample client implementation, and a sample server implementation. These project are both web based, they where tested in a default Tomcat 5.5.23, and a default Active MQ 4.1.1. Active MQ is used as a JMS message broker.

The client consist out of two pages, the first page will initiate the call to the server, the second page will present the result to the user. A sample of the client side spring config is represented below. For Lingo client side 3 beans are defined, the actual service, the JMS broker, and the queue where to send the message to. The last two must also be present in the server side spring config.


<!-- client side proxy-->
<bean id="exampleService" class="org.logicblaze.lingo.jms.JmsProxyFactoryBean">

<property name="serviceInterface" value="org.isthisjava.service.ExampleService"/>
<property name="connectionFactory" ref="jmsFactory"/>
<property name="destination" ref="exampleDestination"/>
</bean>

<!-- JMS ConnectionFactory to use -->
<bean id="jmsFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616"/>
</bean>

<bean id="exampleDestination" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg index="0" value="org.isthisjava.service.ExampleService"/>
</bean>


For the Lingo server side consist out of 4 beans, the actual POJO implementation of the service, a setup for the POJO so that it will listen to incomming messages, and the JMS broker and the queue definition. The last two are also in the client configuration. Take in account that this configuration is a single threaded solution. A single threaded solution is okee for the client side, but the server side should be multi threaded. How to make your server side multi threaded will be discussed in a later article.


<!-- the server side -->
<bean class="org.logicblaze.lingo.jms.JmsServiceExporter">
<property name="service" ref="serverImpl"/>
<property name="serviceInterface" value="org.isthisjava.service.ExampleService"/>
<property name="connectionFactory" ref="jmsFactory"/>
<property name="destination" ref="exampleDestination"/>
</bean>

<!-- the actual implementation of the service - which is only made public for testing purposes -->
<bean id="exampleServiceImpl" class="org.isthisjava.service.ExampleServiceImpl" singleton="true"/>


In the source code added to this article you will find the ExampleService and a simple implementation of this service. For more details please look into the source code.

If you just want to see a demo please install Active MQ and drop the two wars (see binary) in your Tomcat, and navigate to http://localhost:8080/jmswithlingoclient

jmswithlingoclient-src-1.0.zip
jmswithlingoclient-bin-1.0.zip
jmswithlingoserver-src-1.0.zip
jmswithlingoserver-bin-1.0.zip

Wednesday, July 25, 2007

CAS with ageci security

Blink It Digg! Dzone

At my latest project I got the opportunity to use CAS server in combination with acegi security. With this setup it is possible to have a real single sign-on authentication over multiple contexts and servers.

On the acegi security site and the CAS site I could not find a tutorial to get this setup up and running correctly. It took me several days to get a hello world setup up and running. The biggest problem came across was outdated ageci security documentation. It seems that they did some refactoring in there code base! Additional I had some problem to get tomcat (https) configured correctly. This article will give you a guide on how to get this hello world setup up and running from scratch.

My setup is based on tomcat I used tomcat version 5.5.23 as my servlet engine. CAS needs to run on https, for https you need to sign your JDK by generating a certificate and add this to the jks keychain. WARNING generating the certificate use ‘localhost ’ as your name or common name, otherwise tomcat will not except this certificate.


$JAVA_HOME\bin\keytool -delete -alias tomcat -keypass changeit
$JAVA_HOME\bin\keytool -genkey -alias tomcat -keypass changeit -keyalg RSA
$JAVA_HOME\bin\keytool -export -alias tomcat -keypass changeit -file server.crt
$JAVA_HOME\bin\keytool -import -file server.crt -keypass changeit -keystore %JAVA_HOME\jre\lib\security\cacerts
$JAVA_HOME\bin\keytool -import -file server.crt -keypass changeit

For tomcat to accept https request the next few lines should be added to the server.xml. The .keystore file can be found in your home folder.

<Connector port="8443" maxHttpHeaderSize="8192"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" disableUploadTimeout="true"
acceptCount="100" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS" keystoreFile="/path/to/.keystore"
keystorePass="changeit"/>

To get CAS going download the latest 3.x release, I used 3.1 and drop the cas.war in tomcat. For a simple hello world application CAS doesn't need any more configuration. CAS will aunthenticate all user who have the same username as password, I will come back to this later on

Ageci security was for me alot more difficult to setup correctly. The article will only walk you through the basics, for more details I refer to the source code.

<bean id="inMemoryDaoImpl" class="org.acegisecurity.userdetails.memory.InMemoryDaoImpl">
<property name="userMap">
<value>
marissa=marissa,ROLE_USER,ROLE_SUPERVISOR
dianne=dianne,ROLE_USER
scott=scott,ROLE_USER
peter=peter,ROLE_USER
</value>
</property>
</bean>

<bean id="casAuthenticationProvider" class="org.acegisecurity.providers.cas.CasAuthenticationProvider">
<property name="casAuthoritiesPopulator"><ref local="casAuthoritiesPopulator"/></property>
<property name="casProxyDecider"><ref local="casProxyDecider"/></property>
<property name="ticketValidator"><ref local="casProxyTicketValidator"/></property>
<property name="statelessTicketCache"><ref local="statelessTicketCache"/></property>
<property name="key"><value>my_password_for_this_auth_provider_only</value></property>
</bean>

Ageci is set up around the inMemoryDaoImpl, four users are defined marissa, dianne, scott, and peter. This DAO is used to get the credentials for the users who are authenticated by CAS, CAS can only check if a user is authenticated. The CasAuthenticationProvider has a special field 'key' what should be set to some special phrase. This phrase is used with-in CAS to distinguish the different client applications. This is necessary for applications what need extra security for instance for some applications CAS needs to re-check the credentials of the user to match the security requirements.

To see all the CAS magic in action for you self, you can download the source or binary with the following links
caswithageci-bin-1.0.zip
caswithageci-src-1.0.zip

The release notes can be found here

Additional info about this article
I see a casfailed.jsp page