Tuesday Oct 14, 2008

Clojure and Lisp Revival





I have always been fascinated by Lisp, but it just seemed like one of those languages that while theoretically nice was completely impractical.  Lisp environments have either been powerful but proprietary, or have been free but limited in capability.  Although Lisp is one of the oldest language around (circa 1950s!)it has remained a niche language, never quite attracting enough critical mass to make it a serious alternative to mainstream languages such as Java, ruby, or C#.


Clojure might just change that.

It's a Lisp dialect built on top of the JVM, and it solves many problems which have impaired Lisp adoption:
  • Courtesy of the JVM, Clojure has access to the world's largest collection of software libraries. 
  • It's a two way street. Clojure is able to create classes that can be called from Java.
  • Clojure has a cross platform GUI. Love it or hate it, Swing does a reasonable job at solving this problem. My money is on someone leveraging JavaFX libraries to build a DSL with Clojure. Might be a nice alternative to JavaFX script!
  • It's got a free IDE. Enclojure is a Netbeans plugin that provides a namespace browser, editor, code completion, and interaction with REPL. For a Java guy used to the Edit-Compile-Jar-Deploy-Run cycle it's pretty neat to be able to incrementally send expressions to the REPL.
  • It's fast (or at least fast enough). Expressions entered in the REPL (the Read Evaluate, and Print Loop) are compiled directly to Java byte code. As Java gets better at dynamic languages (think invokedynamic!), Clojure gets faster.
  • It's practical. Rich Hickey, the mastermind behind Clojure, has made a few design choices that improve the performance and interoperability with the JVM. For example, Clojure supports vectors, maps, and sequences, all of which map nicely to Java constructs.  

Most importantly, Clojure's functional style is perfectly suited to a future when massively parallel multi-core machines are the norm:

Functional programs eschew the external 'effects' of imperative
programs, and thus become easier to understand, reason about, and test,
since the activity of functions is completely local. To the extent a
portion of a program is purely functional, concurrency is a non-issue,
as there is simply no change to coordinate.
[http://clojure.org/state]

Check it out  here






Tuesday Apr 29, 2008

Apple adds Java SE 6 support



Better late than never....


http://www.macrumors.com/2008/04/29/apple-adds-java-se-6-to-leopard/



Tuesday Apr 22, 2008

A script to add 3rd party artifacts to your maven repository



I find the maven command line very obtuse and have trouble remembering the right incantation to add 3rd party jars to a local repository.


Here is a small bash script which might be useful to others. You will need to edit this for your environment.


#!/bin/bash
# Add 3rd party jars to maven in a batch
# Usage: madd groupid version jar1 jar2 ...
#
# Edit the mvn command as per your repo setup

if [ $# -lt 3 ]; then
echo Usage: $0 groupid version jar1 jar2...
exit 1
fi

GROUPID=$1
shift
VERSION=$1
shift

for file in $\*
do
ARTIFACTID=`echo $file | sed -e 's/\\.jar//'`
mvn deploy:deploy-file -DgroupId=$GROUPID -DartifactId=$ARTIFACTID \\
-Dversion=$VERSION -Dpackaging=jar -Dfile=$file \\
-Durl=http://localhost:8081/nexus/content/repositories/thirdparty \\
-DrepositoryId=thirdparty
done

Thursday Oct 12, 2006

Jini Made Easier - Writing a Jini Service for Seven

Jini Made Easier - Writing a Jini Service for Seven

I gave a presentation to the local Calgary JUG entitled, “Making Jini Easy (or at least easier)”. For those that want to follow along, I have posted the sample Netbeans project at http://mediacast.sun.com/share/warren/ShippingService.zip

This tutorial will show you how to build and deploy a simple Jini service to the Seven container. Seven is a an implementation of the Jini Service Container (JSC) specification. Both Seven and the JSC spec have been developed as part of the cheiron project. As with the Jini platform, Seven is offered under the Apache 2 license.


The JSC specification is a promising direction towards the goal of making Jini easier to use. The basic idea is to let the container handle the heavy lifting with respect to developing and deploying a Jini Service.

Prerequisites

To build and deploy this tutorial you will need the following components:

  • Netbeans (5.5 or 6.0 builds should be fine)

  • JDK 1.5 (note that Seven has an incompatibility with JDK 1.6 – so best to stay on 1.5 for now)

  • A build of the seven suite ( I used 0.1.1 for this tutorial)

Before opening the Netbeans project create a “JSC” library containing the relevant Seven jar files. Here is what mine looks like (you will need to change this to suit your environment)






The Shipping Service Example

The tutorial presents a simple service that calculates shipping costs for packages based on their weight and the destination postal code. The business interface (this is what the client sees) to the service is simple:

package demo;

import java.rmi.RemoteException;

/\*\*
 \*
 \* @author warren
 \*/
public interface ShippingService {
    public float calculateShippingCosts(String postalcode, float packageWeight ) throws RemoteException;
}


For simplicity, our shipping service only takes a destination postal code – but you get the idea behind the interface.

Remote Interface

The remote interface (what the services provides) is as follows:


package demo;

import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.Map;

/\*\*
 \* Remote interface for the shipping service. This is
 \* the "private" backend protocol between the proxy 
 \* and the service.
 \* @author warren
 \*/
public interface ShippingServiceRemote extends Remote {
    public Map getShippingTables() throws RemoteException;
}


If you have not used Jini before, the above may look rather odd., in that the client's view of the service is not the same as what the service actually provides! The missing link here is the “smart proxy”:, which bridges the client to the service. Let's have a look:



package demo;

import java.io.Serializable;
import java.rmi.RemoteException;
import java.util.Map;

/\*\*
 \* proxy that gets downloaded to the client.
 \* The proxy implements caching of rate tables
 \* vended by the backend service. The proxy
 \* provides local lookup of shipping rates.
 \* 
 \* @author warren
 \*/
public class ShippingServiceProxy implements ShippingService, Serializable {
    
    private Map shippingTables;
    private final ShippingServiceRemote server;
    
    /\*\* Creates a new instance of ShippingServiceProxy \*/
    public ShippingServiceProxy(Object connectorStub) {
        server = (ShippingServiceRemote)connectorStub;
    }
    
    public float calculateShippingCosts(String postalcode, float packageWeight) throws RemoteException {
        // Do we need the fetch the rate tables from the service?
        if( shippingTables == null )
            shippingTables = server.getShippingTables();
        
        Float costFactor = (Float) shippingTables.get(postalcode);
        if( costFactor == null )
            throw new IllegalArgumentException("Bad Postal code");
        
        return packageWeight \* costFactor.floatValue();
    }
    
    private static final long serialVersionUID = -2719045781828648539L;
}


The smart proxy is dynamically downloaded to our client when it looks up our service in the Jini LUS. This is all part of the magic of Jini – which we really don't have time to cover here, but please read Jan Newmarch's excellent tutorials if you are curious.


Smart proxies are one of things that makes Jini so powerful. In the above example, we can see that our proxy is performing local caching of shipping rate tables that it receives from the service. This turns most shipping rate calculations into a local lookup in a rate table instead of a remote procedure call. This is a good example of a service which is impractical to implement as a Web Service, but works fine in Jini (imagine the performance penalty of trying to look up several hundred shipping costs per second using a remote ShippingService interface). Now of course, as a service provider we could advertise the ShippingServiceRemote interface - but this exposes a lot implementation detail to our clients. If the algorithm changes we will have to ask our clients to update their code. The use of smart proxies gives us a clean interface along with a flexible implementation strategy.


The only remaining piece is the actual service code. This is where Seven helps us by providing a container that handles much of the service registration and configuration code. Here is our rather simple service:


package demo;

import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.Map;
import net.jini.core.entry.Entry;
import net.jini.lookup.entry.Name;
import org.cheiron.jsc.JSCException;
import org.cheiron.jsc.JSCFailure;
import org.cheiron.jsc.JiniService;
import org.cheiron.jsc.ServiceContext;
import org.cheiron.jsc.ServiceState;

/\*\*
 \* The backend Shipping Service provider.
 \* The private protocol between the provider and proxy is
 \* an exchange of shipping rate tables. This demonstrates
 \* how a proxy can improve performance through caching. 
 \* 
 \* @author warren
 \*/
public class ShippingServiceProvider implements JiniService {
    private ServiceContext context;
    
    public void failureDetected(JSCFailure failure) {
    }
    
    public Entry[] getAttributes(Entry[] attributes) throws JSCException {
        return new Entry[]{ new Name("Shipping Cost Calculator Service") };
    }
    
    public Remote[] getServiceProviders() throws JSCException {
        return new Remote[]{ new ProviderImpl() };
    }
    public Object getServiceProxy(Object connectorStub) throws JSCException {
        return new ShippingServiceProxy(connectorStub);
    }
    public void init(ServiceContext context) throws JSCException {
        this.context = context;
    }
    public void stateChanged(ServiceState newState, ServiceState oldState) {
    }
    
    /\*\*
     \* The Implementation class - builds and returns
     \*  a map of the shipping costs from various postal codes
     \*/
    private class ProviderImpl implements ShippingServiceRemote {
        public Map getShippingTables() throws RemoteException {
            HashMap map = new HashMap();
            map.put("T2N3L2", new Float(1.21));
            map.put("123456", new Float(1.97));
            return map;
        }
    }    
}


In the above example, the Remote interface is implemented as an inner class. There are a few required life cycle methods – most of which we leave empty for this example.


By implementing the JiniService interface, our service can delegate many tasks to the Jini Service Container. These include:

  • Service Registration with the LUS (Lookup Service)

  • Lease management of our registration with the LUS

  • Life Cycle Management. The container manages creating, starting, stopping and destroying our service

  • Exporting our service proxy

  • Service Configuration

Seven provides other features that I am not going to cover here (for example, server side lease management and service state persistence ).

Building and Deploying

To deploy our service to Seven, we need to create a deployment descriptor. You will find this under the config/ directory in the sample Netbeans project:


<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jsc-descriptor
    xmlns="http://www.cheiron.org/jsc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.cheiron.org/jsc http://www.cheiron.org/schema/jsc.xsd">
    
    <service-group-def oid="2.3.6.1.4.12543.2.3" version="0.1.1">
        
        <description-group>
            <description>Provides Shipping cost calculations for packages</description>
            <display-name>Shipping Cost calculator</display-name>
        </description-group>
        
        <grant-def>
            <permission
                class="net.jini.discovery.DiscoveryPermission" id="perm.discovery">\*</permission>
        </grant-def>
    </service-group-def>
    
    <service-def class="demo.ShippingServiceProvider"/>
    
</jsc-descriptor>

The above descriptor declares a service group which is a mechanism used to manage like services as a unit. IANA Object ID's are used to uniquely define service groups (disclaimer: the above OID is not a valid number – it's one I made up!). I'm not sure I am crazy about the use of OIDs as they seems a bit cumbersome to me. My preference would be to use java style package names (reverse dns).


Any permissions required by the service are declared in the deployment descriptor. Seven takes care of standard permissions that are needed to export your proxy, so these do not need to be declared.


Finally, we have our ant build.xml that creates our service archive (.sar) that is deployed via the seven Admin UI:


<?xml version="1.0" encoding="UTF-8"?>
<!-- You may freely edit this file. See commented blocks below for -->
<!-- some examples of how to customize the build. -->
<!-- (If you delete it and reopen the project it will be recreated.) -->
<project name="jsc-demo" default="default" basedir=".">
    <description>Builds, tests, and runs the project</description>
    <import file="nbproject/build-impl.xml"/>
    <property file='build.properties'/>
    
    <taskdef resource="cheirontasks.properties">
        <classpath>
            <fileset dir="${seven.home}/tools/jini/lib" includes="\*.jar"/>
        </classpath>
    </taskdef>
     
    <path id="jsc">
        <pathelement location="build/classes"/>
        <fileset
        dir="${seven.lib}"
        includes="cheiron-util.jar,jsc-platform.jar,jsc-platform-lib.jar,serviceui.jar"/>  
    </path>
    
    <path id="jsc-test">
        <path refid="jsc"/>
        <pathelement location="build/test/classes"/>
        <path path="lib/jsk-platform.jar"/>
    </path>
    
    <target name="create-dl" depends="compile">
        <!-- Create the Service jar file -->
        <dljar
            destfile="build/services.jar"
            platform="jsc"
            inroot="demo">              
            <classpath refid="jsc"/>  
            <class name="demo.ShippingServiceProvider"/>         
            <rootdir name="${build.dir}/classes"/>
        </dljar>
        <!-- Create the codebase download jar file.  -->
        <dljar destfile="build/services-dl.jar" platform="jsc-dl">
            
            <classpath refid="jsc"/>
            <rootdir name="demo"/>
            <apiclass name="net.jini.lookup.entry.Name"/>   
            <proxyclass name="demo.ShippingServiceProxy"/>
        </dljar>
    </target>
    
    <target name="create-sar" depends="create-dl">
        <sar
            destfile="dist/${ant.project.name}-${version}.sar"
            jscxml="config/shippingservice-jsc.xml"
            version="0.1.1">
            
            <lib dir="${build.dir}" includes="services.jar"/>      
            <libdl dir="${build.dir}" includes="services-dl.jar"/>
        </sar>
    </target>
    
    <target name="run-seven">
        <exec executable="${seven.cmd}" />
    </target>
    
    <target name="jini-servicebrowser">
        <exec executable="${incax-browser}" spawn="true"/>
    </target>  
</project>


Seven provides two Ant tasks (dljar and sar) that are used to create the service jars and the service archive. The dljar task (based on the ClassDep code found in the Jini Starter kit) makes it easier to generate download jar files with the correct classes and preferred list. Codebase is beyond the scope of this blog entry, but suffice to say that the service-dl.jar file created in the above example contains the classes that must be dynamically downloaded to our client. When we deploy the .sar file to seven, it will ensure that the codebase is set to correctly annotate our service proxies. The Seven JSC runs it's own internal HTTP server for the codebase jar files.


If you have successfully built the project (run the create-sar task), you should be able to bring up the seven admin UI and start your service. Make sure Seven is running (run seven.bat from the install directory, or you can try the included ant task).


In order to access the Seven UI you will need a Jini service browser that supports the ServiceUI specification. In a nutshell, ServiceUI is way of attaching a graphical interface to a service. A ServiceUI client can dynamically load this UI to interact with and manage a remote service instance. You can use the browser included in the Jini Starter kit, or another nice alternative is the free service browser available from Inca X. The following screen shot shows the seven Admin ServiceUI running under IncaX:





To deploy your service, install the sar file that has been created under your dist/ directory. From the above menu, choose ServiceArchive, browse your .sar file, and upload the archive to Seven. Once uploaded, your service group should show up in the JSC container panel on the right hand side. Right click on your service group, and choose “Add Service”. This should prompt you for service and group instance names.


Right click over the new service entry and select "Start" from the context menu. You should see your service interface (ShippingService) show up in left panel of the browser. This confirms that your service has been deployed and is now registered with the Jini Lookup Service (LUS):






Let's wrap up by showing you one last neato feature of the Inca X browser. If you expand the interface tree for your service, you can see the methods that your service provides. Inca X lets you invoke service methods via the browser. For simple testing, this saves your from writing a test client. Click on your method (in our case calculateShippingCosts), enter parameter values for the call, and press the invoke button:






You should see the result of invoking the service (note that our sample service only accepts two postal codes!).

Now that wasn't so hard, was it?

Thursday Oct 05, 2006

Summary Jim Waldo's keynote at the 10th Jini Community Meeting

Summary of Jim Waldo's Keynote at the 10th JCM


[Disclaimer: This is my summary of Jim's keynote from the last JCM. It is not a transcript; Any errors are probably mine! Thanks to Jerome Bernard for video taping Jim's presentation! The presentations and videos from the JCM can be found here]


Jim is thinking about things that cause a quantum jump in complexity. You are OK, and then something changes in a big way.


The basic jumps in complexity occur at these points (I add abbreviations here to refer to them later on)


  • Sequential (SEQ)– life is good, life is easy.

  • Multi-threaded (MT) – takes retooling and a competent programmer to think about MT

  • Multi-Process (MP) – For everyone other than kernel developers, this came before MT

  • Multiple Machines (MM) on the same network. Not the same as multi-process, but some people think it is

  • Multiple Untrusted Machines (MMU) – Essentially the web


All of the above cause discontinuities in the programming model. As you move through each stage, you lose something:


  • seq -.-> MT – you lose ordering (multiple things can happen at once) This is hard – as we naturally think sequentially.


  • Move to multiple processes – lose single context (i.e. A shared context that we can rely on). Global state is used all the time in development (think anything static).


  • Multiple Processes to Multiple Machines – state gets lost. Global State of your “system” is a fiction. There is no consistent state in an interesting distributed system (Jim references Lamport's work on this). Distributed OS projects attempt to introduce global state – they have largely failed.

  • Move to untrusted machines. You lose trust. In the difficult position of not knowing who you can trust.

But you also gain some things as you move through the discontinuities (otherwise why would you do it?)


  • Seq-> MT – you gain parallelism

  • MT – MP – you gain isolation (gives you safety)

  • MP to MM gives you independent failure (parts of your system can survive if things fail)

  • MM to MMU – gives you scale (web scale, Internet scale). Use someone else's resources (or allow someone to use ours).

The Platform


The platform – allows us to do the work. The model the developer sees:


  • SEQ – A batch OS is fine.

  • MT -language extensions needed for correctness (ensure system wont re-order things underneath you)

  • MP – need communication mechanism between the processes.

  • MM – Not clear what the platform is? Attempts include RPC (invented at PARC), CORBA, Jini, XML/SOAP. Not clear we have figured this out. We know what it is not. Grids trying to be the platform.


Most grids are an attempt to do batch on a large scale (scientific). Scheduling jobs. Use individual OS in any way you wish – not a platform, but a way of aggregating platforms. How do you give a programming abstraction. Jini is a good attempt – but only the beginning. What is outside the grid, vs inside. Outside – untrusted, inside is trusted – mutual trust


Two discontinuities – inside/outside – we are conflating them – trying to solve all the problems at once won't work. We need two solutions.


Jini 1.0 – built for the 1st discontinuities – MM but assumes full trust. Built on mobile code.

Ad-hoc organization – changes over time. When a service enters into the system, you could trust it.

Failure handled – but not a failure of trust.

Types – the way which you identity things


Jini 2.0 – Multiple Untrusted Machines. Adds security. This is hard to do with mobile code. Adds a lot of complexity (e.g. proxy verification). Perhaps too hard.

Configuration – deployment control. Deployment errors cause a lot of failures in distributed systems. A lot of the complexity is making services reliable for all possible deployments. Maybe we could communicate the reliability needs in the language. Needs to be part of the platform.


Program vs. deploy – we are trained to keep them separate – but this probably makes life harder. Famous disclaimers “We will put management in later” (just like “we will put security in later”).


Services – the things we assume are always there (but sometime they might not be!) Example: persistence. A file system may not always be there in all environments. What would a good persistence service look like?


Containers – is a function converting a type to another type. Must be able to import things, give bindings, yields another container, Containers are type functions.


Virtual machines. JVM is an example. VM is the important thing – not necessarily the JVM. Universal binary allows us to move code and data. Jini is Java VM thing. Other Vms might be interesting (e.g. ones that fix classloader problems?) The abstraction is the important thing.


Feeling of Deja Vu for Jim. Back when all kinds of different O/S existed there were lots of debates “Why mine is better than yours”. What arose was UNIX and the “other” (i.e. There was a lot of convergence about what an O/S looks like). Model of the platform happened after lots of experimentation and discussion. Are we at the same stage as 30 years ago with O/S – a breakthrough may be close.


Wednesday Jul 05, 2006

Running the SEAM Booking demo on Glassfish & Netbeans

For those of you interested in playing with JBoss SEAM on Glassfish, here are some tips which will hopefully get you going.


Disclaimer: I got this working, but I don‘t claim that my hacks are the right solution. There seem to be a few quirks/bugs in the booking demo that are problematic on Glassfish.


Before proceeding you will want to read Brian and Roger's blogs on the subject.


Here are the modifications that I made to the demo (note, no modifications to SEAM 1.0.1. are required):


Create a Netbeans enterprise project

You might want to use Brian‘s Netbeans project as a starting point, or alternatively (the route I chose) – create a Netbeans enterprise project and import the SEAM booking demo code into the project.

Update ejb-jar.xml

The ejb-jar from the example contained the binding declaration, but was missing the interceptor definition (I gather JBoss App Server does not require this). This is what my modified ejb-jar.xml looks like:

<ejb-jar>
<assembly-descriptor>
<interceptors>
<interceptor>
<interceptor-class>org.jboss.seam.ejb.SeamInterceptor</interceptor-class>
<!-- use other elements as per your requirement-->
</interceptor>
<!-- define other interceptors here-->
</interceptors>
<interceptor-binding>
<ejb-name>\*</ejb-name>
<interceptor-class>org.jboss.seam.ejb.SeamInterceptor</interceptor-class>
</interceptor-binding>

</assembly-descriptor>
</ejb-jar>

Update web.xml

The web.xml setup is esentially as per the SEAM documentation with the caveat that Glassfish requires you to declare local ref‘s to your session beans (There is probably a good reason for this – but JBoss seems to get away without these declarations). Here is the modified web.xml (note that I named my project “reservit” and this is reflected in the ejb local ref‘s. You will need to update this to match your project deployment descriptor).

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

<!-- Seam -->
<listener>
<listener-class>org.jboss.seam.servlet.SeamListener</listener-class>
</listener>

<!-- Propagate conversations across redirects -->
<filter>
<filter-name>Seam Redirect Filter</filter-name>
<filter-class>org.jboss.seam.servlet.SeamRedirectFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>Seam Redirect Filter</filter-name>
<url-pattern>\*.seam</url-pattern>
</filter-mapping>

<!-- JSF -->

<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>

<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param>

<context-param>
<param-name>facelets.DEVELOPMENT</param-name>
<param-value>true</param-value>
</context-param>



<!-- Todo: this is already provided in the init code - not sure if it is needed
-->
<context-param>
<param-name>org.jboss.seam.core.init.jndiPattern</param-name>
<param-value>java:comp/env/reservit/#{ejbName}/local</param-value>
</context-param>

<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

<!-- Faces Servlet Mapping -->
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>\*.seam</url-pattern>
</servlet-mapping>

<ejb-local-ref>
<ejb-ref-name>reservit/BookingListAction/local</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local>org.jboss.seam.example.booking.BookingList</local>
<ejb-link>BookingListAction</ejb-link>
</ejb-local-ref>
<ejb-local-ref>
<ejb-ref-name>reservit/RegisterAction/local</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local>org.jboss.seam.example.booking.Register</local>
<ejb-link>RegisterAction</ejb-link>
</ejb-local-ref>
<ejb-local-ref>
<ejb-ref-name>reservit/ChangePasswordAction/local</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local>org.jboss.seam.example.booking.ChangePassword</local>
<ejb-link>ChangePasswordAction</ejb-link>
</ejb-local-ref>
<ejb-local-ref>
<ejb-ref-name>reservit/HotelBookingAction/local</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local>org.jboss.seam.example.booking.HotelBooking</local>
<ejb-link>HotelBookingAction</ejb-link>
</ejb-local-ref>
<ejb-local-ref>
<ejb-ref-name>reservit/HotelSearchingAction/local</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local>org.jboss.seam.example.booking.HotelSearching</local>
<ejb-link>HotelSearchingAction</ejb-link>
</ejb-local-ref>
<ejb-local-ref>
<ejb-ref-name>reservit/LoginAction/local</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local>org.jboss.seam.example.booking.Login</local>
<ejb-link>LoginAction</ejb-link>
</ejb-local-ref>
<ejb-local-ref>
<ejb-ref-name>reservit/LogoutAction/local</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local>org.jboss.seam.example.booking.Logout</local>
<ejb-link>LogoutAction</ejb-link>
</ejb-local-ref>
</web-app>

Update the JPQL queries.

I found the booking example queries would not parse correctly with the Glassfish/Toplink persistence manager [note: you need to update the persistence.xml file to use Glassfish/Toplink]. I presume this is a standard‘s thing – but I don‘t know which implementation is correct. You will need to change queries of the form:


bookings = em.createQuery("from Booking b where b.user.username = :username order by b.checkinDate")

To this:

bookings = em.createQuery("select b from Booking b where b.user.username = :username order by b.checkinDate")

Fix the s:link tags

I found that the linkStyle=“button” attribute of the SEAM link tag causes XML parsing errors. This could be a facelets and/or JSF 1.2 bug? (suggestions welcome). I removed this attribute – which fixes the XML parsing error at the expense of not rendering the link as a button. Change this:

<s:link value="Cancel" action="login"  linkStyle="button" buttonClass="button"/>

To this:

<s:link value="Cancel" action="login" buttonClass="button"/>

Fix XML parsing wierdness.

This falls into the not-really-sure-what-I-am-doing category. I found a lot of parsing errors with the facelet .xhtml files. In particular:

  1. I found the DOCTYPE header on most of the .xhtml files caused problems. This appears to be related to the facelets templating mechanism. Getting rid of the header made this problem go away.

  2. Non breaking spaces such as amp;nbsp; or amp;#160; caused parsing problems. Once again – this looks like some kind of templating problem.

  3. Beware of comments. While experimenting I would often put suspect code in XML comments. That is, until I realized the comments are parsed by the facelets template engine, causing runtime parsing errors.

If you have suggestions please leave a comment!

Monday Jun 26, 2006

JPA Annotation Reference


For those dabbling in EJB 3 and JPA, Oracle has a nice online reference for annotations. You can find it here

Wednesday Mar 01, 2006

Jini and Lisp anyone?





Dynamic typed languages seem to be garnering a lot of attention these days. It got me to thinking, could you implement a Jini like system on top of Lisp? (or pick your favorite language du jour). You would need support for the following:


  • Dynamically loading downloaded code. No problem for Lisp here.

  • Performing some kind of verification on the safety and trustworthiness of that code. Digital code signing should be easy, but would Lisp support something equivalent to the Java byte code verifier?

  • A sandbox environment to safely run the downloaded code. Could you do this efficiently in Lisp, or would you need major surgery to the underlying VM (or whatever it's called in Lisp parlance :-) )



My contribution to such an effort would be the name (every new project needs a cool name). How about Jisp? Or maybe Lini?






Thursday Jul 07, 2005

Matisse

Matisse is the new GUI builder in NetBeans 4.2.

All I can say is WOW!

This is so much more intuitive/easy to use vs. the old GridBagLayout. And for the Eclipse fans out there - this is yet another great reason to take Netbeans out for a test drive.

Let a thousand new Swing applications bloom!

Thursday May 19, 2005

Jini vs. Indigo

In light of comments made comparing Jini and Indigo Craig McMurty's blog expands on the differences between the two, and concludes
In the years since Jini, though, we have learned a lot about how NOT to design those programming models, and those lessons suffuse Indigo

OK, fair enough, I didn't expect Microsoft to actually endorse Jini (although I am reasonably confident they will eventually "invent" something just like it. The benefits of mobile are hard to ignore).

There are a couple of specific points raised that are worth exploring:

A more important difference between Jini federations and Indigo applications is that Jini clients and servers share classes, whereas Indigo clients and servers only share contracts and schemas.

Not to be pedantic, but well written Jini services usually share interfaces, not classes. It's a small, but important difference. Well designed interfaces don't change often, while classes do. For example, the standard services that ship with the JSK have been remarkably stable over the years, even though the implementations have changed with each release.

Of course the nice thing about mobile code is that clients don't care about having the right version of a class installed. The implementation of the interface is dynamically downloaded. Once you grok this idea you get that "AhA"! moment when you realize the power this affords:

  • Protocols are irrelevant. Clients can communicate over RMI, SOAP, HTTP, JXTA, or any other protocol you might require.
  • Smart downloadable proxies allow for flexible client-service interaction. The proxy can be a thin veneer (like a web service) that calls out to the service to perform all of the work, or it can be "smart", and offload computation and bandwidth from the service. The WS-\* folks like to remind us that it's all about "loosely coupled" services. Yes - this is a good architecural choice for many systems - but not all. Jini lets you build for both design centres.
  • Jini supports multiple implementations of a service interface with varying QoS attributes (confidentiality, availability, performance, etc.). Clients don't have to change their code to change QoS - because the code is downloaded to their VM.
Indigo is considered "good" because it decouples the service code from the description of the service. I understand the essence of the argument - but I don't buy it. The service code might be decoupled - but you have introduced a very complex configuration language (WSDL and assorted goodies - whose spec weighs in at several hundred pages). And there is no free lunch afforded by describing services in XML. Your purchasing service still needs the right code installed that understands the semantics of an invoice.

Jini has it's own service description language. It's called a Java. It's simple, elegant and powerful. Mobile code allows Jini clients to gain isolation from at least some of semantic details of the service. The code behind the interface is never "installed" by the client, rather it comes dynamically as required. A nice side effect is that the client always has the "right" version of the code.

Jini components connect to each other via the initial intermediation of a service locator, which compromises their autonomy, for they are tied together by the service locator in just the same way that COM components are tied together via the registry.

Well components have to find each other some way, don't they? One could also say that WS-\* clients compromise their autonomy because they rely on SOAP and UDDI for discovery. Once again, Jini's solution is simple, consistent and powerful. It's also not fair to compare Jini's lookup service with the COM registry. To be best of my knowledge COM has no notion of service registration leasing, lookup based on matching interface type, and so on.

Thursday Jan 13, 2005

Jini as a replacement for WSRP

I was attending a presentation on WSRP, when it struck me that Jini could solve this problem in a much more elegant fashion.

WSRP "Web Services for Remote Portlets" is a standard for aggregating content from remote producers. A typical use case might be your HR department exporting an employee lookup portlet that can then be aggregated into other portals throughout the organization. WSRP is an attractive alternative vs. having to distribute and install the portlet in each portal instance.

During the presentation I got to thinking about how Jini could solve this problem. What if each remote producer was a Jini service that implemented a well known Portlet API (let's call them Jinlets). Remote Jinlet services register with all available Jini Lookup Services (LUS). An aggregating Jini portal would show the user a list of all Jinlet services that can be found in the LUS. The user would choose which Jinlets they want to subscribe to.

This solution would have all the administrative benefits of WSRP (namely, zero installation effort on the aggregating portal). But a Jini solution would offer additional benefits over WSRP.

WSRP introduces additional latency because user interaction is required to be passed through the aggregating portal to the remote provider. This interaction is over SOAP/HTTP - not exactly the speediest protocol on the planet.

Jini could support this model (i.e. all the "smarts" are on the remote provider end), but it could also support smart proxies where some or all of the logic is on the portal consumer side of the wire. Additionally, Jini is protocol agnostic, so communication to the remote service could use a high performance protocol.

You could also do some interesting things that leverage Jini's self adapting nature. Remote services that go down would no longer be registered in the LUS, allowing the aggregating portal to alter it's list of available services. Service availability can be increased by running multiple copies of the remote service. For example, user's probably don't care which particular instance of a stock quote service they subscribe to.

What do folks think? Is this a good idea or just crazy talk :-)

About

Things that amuse me

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today
News

No bookmarks in folder

Blogroll