Planet ObjectWeb

January 29, 2008

Orbeon

Default face

Keeping your session alive

Rotor

A couple of weeks ago I attempted to order prints from Flickr. I added a few photos to my cart and was redirected to a service called QOOP. This has a neat interface that allows you organize photos for printing in a book format. I played a bit with the interface and then was caught by other tasks. When I came back to my browser window and attempted to preview the photo album, I got a wonderful error message about a session having expired. The result: my album was lost. I gave up.

My adventure with expired sessions is quite common and I can bet you have had this kind of issues in the past. The least that can be said about this is that it is not user-friendly!

To address this kind of issues, we recently introduced a new feature in Orbeon Forms called the “session heartbeat”. The idea is that if you happen to leave a browser window open on your computer, chances are that you will get back to that window and keep using the application. The last thing you want to happen when you come back is lose your session and therefore your data, as happened to me.

This is not always a correct guess of course: you may just happen to leave a window or tab open without planning to use it again. Conversely you may have a page which is not actually visible, for example in your browser history, yet you will come back to it. This approach wouldn’t be good for banking applications either. Still, in many situations, such as filling-out large forms, it sounds like a good idea to keep your session alive for open pages.

To achieve this goal you could make all server sessions longer. However this is harder to configure for the application developer, and this won’t discriminate between pages that are actually open on a client and the ones that are not. And while it may be ideal to have infinitely long sessions, unfortunately many applications are not ready for this kind of approach.

So we turned to the idea of implementing a “session heartbeat”. Here is how this works:

Note that whenever an application keeps sessions alive for a long time, it is a good idea to keep as little data as possible in the session. The Orbeon Forms XForms engine itself uses a global state store and does not use session objects for storage, but do remember to keep your sessions small!

Hopefully, this will help prevent many occurrences of the infamous “session expired” error message. The beauty of it is that as an Orbeon Forms application developer you don’t have to worry about anything: the session heartbeat is enabled by default (but it can be turned off globally in properties.xml or individually for each page).

January 29, 2008 03:36 PM

January 27, 2008

Christophe Hamerling

Default face

Too many open files IOException with large number of Axis2 Servic

This is a problem we met in the PEtALS SOAP Binding Component with large number of Axis2 Service Clients.
In this case, this error happens when too many sockets are open ant are waiting to be closed. Even if I have found some JIRAs about this problem and possible solutions, the only one which work for us is to cleanup the connection after each service call.
It is done like this :

...

ServiceClient client = new ServiceClient(null, service);

Options options = new Options();

...

options.setCallTransportCleanup(true);

client.setOptions(options);


OMElement outBodyElement = null;

try {

outBodyElement = serviceClient.sendReceive(soapAction, inBodyElement);

} catch (AxisFault e) {

throw e;

}



After 10 minutes test with 200 threads creating 'one shot ' ServiceClient and almost 275000 service calls, all worked fine.

January 27, 2008 11:50 PM

Going to JavaPolis 07

See you next week JavaPolis '07 on the OW2 Consortium booth to talk about and make some 'demos' of the PEtALS Enterprise Service Bus project.



January 27, 2008 11:50 PM

PEtALS Standalone 1.4.3

PEtALS Standalone platform 1.4.3 is out. This is a maintenance release.
Look at the release notes for more details.

January 27, 2008 11:50 PM

CIMERO2 Editor for PEtALS ESB

The CIMERO2 editor is an Eclipse plugin originally developed by Bull. This plugin provides features to create a visual representation of your Enterprise Service Bus based architecture. After the design step, the plugin offers the possibility to generate the JBI artifacts (Service Assemblies), and the Ant deployment scripts which will be used to deploy the configuration on the ESB.

We, at eBM WebSourcing, are currently working on better integration of the PEtALS JBI components. You can find a Flash demonstration on how we you can use this plugin on the PEtALS project website demonstration page.

Finally, it is good to notice that this plugin is currently under integration into the Eclipse SOA Tools Platform project (Eclipse STP).



January 27, 2008 11:50 PM

Installing SVN Client on Mac OSX

I am happy to see that Fink (http://finkproject.org/) is no more needed to easily install a Subversion client on Mac OSX. A client has been packaged by this guy Martin Ott (http://homepage.mac.com/martinott/).
Installation done by clicking on the package...

I am also happy to see that there is a Subversion GUI client for OSX. Working with terminal is cool but sometimes clicking on the mouse is not so bad...
You can found this client on 'La chose interactive' website (http://www.lachoseinteractive.net/fr/communaute/subversion/).

Configuration seems very intuitive... Going to test it for PEtALS project...

January 27, 2008 11:50 PM

PEtALS PACK 2.0

Friday (evening) September 28th 2007



PEtALS ESB 2.0 is finally out!
It is released at the same time as a 'pack' including all new/compatible modules which have been developed since months.
These modules are :
Complete release note will be available on the PEtALS Website.


January 27, 2008 11:50 PM

PEtALS last week releases

We have done some releases last week :

1. petals-standalone 1.4 :
    - Integration of a faster message transporter (Dream based)
    - Load balancing
    - Robustness
    - and of course several bug fixes and code optimization

2. petals-component-framework 2.0 :
    - This framework replaces the Component Development Kit (also known as CDK). It allows developers to quickly create powerful JBI components.

3. petals-bc-soap 2.0 :
    - Based on the petals-component-framework.
    - WS security
    - WS notification

Zip archives and documentation are available for download on the PEtALS downloads page.


January 27, 2008 11:50 PM

Road to PEtALS 2.0

PEtALS 2.0 is on the way. The beta version will be out in few weeks with cool features :




January 27, 2008 11:50 PM

PEtALS Azalee Pack

The PEtALS Azalée Pack is finally out. It includes all the latest stable versions of project artefacts.
You can download it here and get release note here.

Technorati Tags     ,,,,,,

January 27, 2008 11:50 PM

PEtALS community news - May

PEtALS news #1, 2007 May 16th


The PEtALS community is growing. Thanks to everyone for the interest you give to the project. Here is the first newsletter dedicated to this great project...


Releases and more

More information on the future release note...

Main developments


Documentation


Others


Please do not hesitate to send your comments, ideas, and more...







Technorati Tags     ,

January 27, 2008 11:50 PM

Creating fully compatible JBI components

As JBI container developers (PEtALS), we have created a framework which allows developers to easily create JBI components.

This Component Development Kit (also called PEtALS CDK) is based on the JBI specification and allows to create components which are 100% compatible with the JBI specification. In other words, you can use the CDK to create components that can be installed on all JBI implementations.

Note that most of the PEtALS components (Service Engines and Binding Components) are based on this CDK.
An online documentation is available on the projet wiki here and you can download the CDK here.

Technorati Tags     ,

January 27, 2008 11:50 PM

Implementing the DynamicMBean interface

Implementing DynamicMBean interface

Introduction

Using JMX (Java Management eXtensions) to manage part of your application is a great java feature. The standard Mbeans mechanisms which consist of creating a class which implements an MBean interface is quite simple and already allows to manage most of your application.
In this article, I will describe how can we implements the DynamicMBean interface to do more 'complex' things. Especially, we will look on how we can we expose and modify a set of properties, and how can we expose methods by specifiing their names (The java code will be more clear than my poor english).

The following examples are taken from the work I have done on the PEtALS CDK (Component Development Kit) in order to expose a set of JBI extensions and bootstrap methods for management.

How to expose a set of properties?

The standards MBeans automatically expose the setters and getters methods as MBean attributes. Imagine that you have a set of properties (a HashMap/Properties...). How can you manage this object, how can you change a value in the set? Simply by creating an implementation of the DynamicMBean interface.

The following code snippet shows how we can do such a thing.


    /*
* (non-Javadoc)
*
* @see javax.management.DynamicMBean#getAttribute(java.lang.String)
*/

public synchronized Object getAttribute(String attribute)
throws AttributeNotFoundException, MBeanException, ReflectionException {

String value = managedBootstrap.getComponentPropertiesManager()
.getProperties().getProperty(attribute);
if (value != null
&& !value
.startsWith(ComponentPropertiesManager.MANAGED_METHOD_PREFIX)) {
return value;
} else {
throw new AttributeNotFoundException("Attribute '" + attribute
+ "' does not exists");
}
}

/*
* (non-Javadoc)
*
* @see javax.management.DynamicMBean#getAttributes(java.lang.String[])
*/

public synchronized AttributeList getAttributes(String[] attributes) {
AttributeList list = new AttributeList();
for (String name : attributes) {
String value = managedBootstrap.getComponentPropertiesManager()
.getProperties().getProperty(name);
if (value != null
&& !value
.startsWith(ComponentPropertiesManager.MANAGED_METHOD_PREFIX))
list.add(new Attribute(name, value));
}
return list;
}

/*
* (non-Javadoc)
*
* @see javax.management.DynamicMBean#setAttribute(javax.management.Attribute)
*/

public synchronized void setAttribute(Attribute attribute)
throws AttributeNotFoundException, InvalidAttributeValueException,
MBeanException, ReflectionException {
String name = attribute.getName();
if (managedBootstrap.getComponentPropertiesManager().getProperties()
.getProperty(name) == null) {
throw new AttributeNotFoundException(name);
}

Object value = attribute.getValue();
if (!(value instanceof String)) {
throw new InvalidAttributeValueException(
"Attribute value not a string: " + value);
}

// set the property and save the properties file
managedBootstrap.getComponentPropertiesManager().getProperties()
.setProperty(name, (String) value);
try {
save();
} catch (IOException e) {
throw new MBeanException(e);
}
}

/*
* (non-Javadoc)
*
* @see javax.management.DynamicMBean#setAttributes(javax.management.AttributeList)
*/

public synchronized AttributeList setAttributes(AttributeList list) {
AttributeList result = new AttributeList();

for (Object object : list) {
Attribute attr = (Attribute) object;
String name = attr.getName();
Object value = attr.getValue();
if (managedBootstrap.getComponentPropertiesManager()
.getProperties().getProperty(name) != null
&& value instanceof String) {
managedBootstrap.getComponentPropertiesManager()
.getProperties().setProperty(name, (String) value);
result.add(new Attribute(name, value));
}
}

try {
save();
} catch (IOException e) {
return new AttributeList();
}
return result;
}

The previous methods are the ones which are called by the JMX implementation for management. In our case it is quite simple since a property entry is directly mapped into an attribute...

Note 1 : The managedBootstrap attribute is a class which contains a Properties object.
Note 2 : We persist the properties in a file each time a property is modified.

In order to expose these attributes, we will see later that we need to create a set of MBeanAttributeInfo that will be used by the getMBeanInfo method to create the information object used by JMX to expose all of this.

    /**
* Dynamically get attributes for the MBean. The attributes are the ones
* from the properties file.
*
* @return
*/

protected MBeanAttributeInfo[] getAttributesInfos() {
// get the attributes names as sorted strings
Set<String> attributeKeys = managedBootstrap
.getComponentPropertiesManager().getExposedAttributeKeys();

// build the MBeanAttributeInfo
MBeanAttributeInfo[] attrs = new MBeanAttributeInfo[attributeKeys
.size()];
Iterator<String> it = attributeKeys.iterator();
for (int i = 0; i < attrs.length; i++) {
String name = it.next();
attrs[i] = new MBeanAttributeInfo(name, "java.lang.String",
"Property " + name, true, true, false);
}
return attrs;
}

How to expose a set of methods?

Building the MBeanInfo

In the previous chapter, I have introduced how we can dynamically expose properties. Now we will focus on how we can choose the methods to expose through JMX. There are several methods to do this. Here I have choosen to expose only the public methods that are programatically defined in a list. I have choosen this simple way to allow the component developer to simply define the methods he wants to expose by returning a list of methods names... Simple and efficient!

    /**
* Dynamically get the operations for the MBean. The operations are defined
* in the properties manager with a special prefix.
*
* @return
*/

protected MBeanOperationInfo[] getOperationsInfos() {
List<String> methods = managedBootstrap.getComponentPropertiesManager()
.getExposedMethodNames();
MBeanOperationInfo[] result = null;

List<MBeanOperationInfo> operations = new ArrayList<MBeanOperationInfo>();
Method methodList[] = managedBootstrap.getClass().getMethods();

for (int i = 0; i < methodList.length; i++) {
Method method = methodList[i];
String name = method.getName();

// add method if it has been defined by the user
if (methods.contains(name)) {
MBeanOperationInfo oper = new MBeanOperationInfo(
"Operation description", method);
operations.add(oper);
}
}

result = new MBeanOperationInfo[operations.size()];
operations.toArray(result);

return result;
}

This time again, we are are creating a set of MBeanOperationInfo from a list methods names. We retrieve the methods from the class we want to manage from the managedBootstrap class by reflection.

This method will be then used to create the MBeanInfo that is returned by the method getMBeanInfo:

    /*
* (non-Javadoc)
*
* @see javax.management.DynamicMBean#getMBeanInfo()
*/

public synchronized MBeanInfo getMBeanInfo() {
// get the attributes
MBeanAttributeInfo[] attrs = getAttributesInfos();
// get the operations
MBeanOperationInfo[] opps = getOperationsInfos();

// create MBeanInfo with no constructors and no notifications
return new MBeanInfo(this.getClass().getName(),
"Property Manager MBean", attrs, null, opps, null);
}

Invoking a method

Doing java reflection is out of this article scope. Have a look on the implementation to see how it is done.

Complete implementation


/**
* PETALS - PETALS Services Platform.
* Copyright (c) 2007 EBM Websourcing, http://www.ebmwebsourcing.com/
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* -------------------------------------------------------------------------
* $Id$
* -------------------------------------------------------------------------
*/

package org.objectweb.petals.component.common;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.AttributeNotFoundException;
import javax.management.DynamicMBean;
import javax.management.InvalidAttributeValueException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.ReflectionException;
import javax.management.RuntimeOperationsException;

/**
* The MBean used to expose component attributes and operations via JMX.
*
* @author Christophe HAMERLING - eBMWebSourcing
*
*/

public class ExtensionMBean implements DynamicMBean {

private ManagedBootstrap managedBootstrap;

private final static Hashtable<String, Class<?>> primitiveClasses = new Hashtable<String, Class<?>>(
8);
{
primitiveClasses.put(Boolean.TYPE.toString(), Boolean.TYPE);
primitiveClasses.put(Character.TYPE.toString(), Character.TYPE);
primitiveClasses.put(Byte.TYPE.toString(), Byte.TYPE);
primitiveClasses.put(Short.TYPE.toString(), Short.TYPE);
primitiveClasses.put(Integer.TYPE.toString(), Integer.TYPE);
primitiveClasses.put(Long.TYPE.toString(), Long.TYPE);
primitiveClasses.put(Float.TYPE.toString(), Float.TYPE);
primitiveClasses.put(Double.TYPE.toString(), Double.TYPE);
}

/**
* Creates a new instance of {@link ExtensionMBean}
*
* @param bootstrap
*/

public ExtensionMBean(ManagedBootstrap bootstrap) {
this.managedBootstrap = bootstrap;
}

/*
* (non-Javadoc)
*
* @see javax.management.DynamicMBean#getAttribute(java.lang.String)
*/

public synchronized Object getAttribute(String attribute)
throws AttributeNotFoundException, MBeanException, ReflectionException {

String value = managedBootstrap.getComponentPropertiesManager()
.getProperties().getProperty(attribute);
if (value != null
&& !value
.startsWith(ComponentPropertiesManager.MANAGED_METHOD_PREFIX)) {
return value;
} else {
throw new AttributeNotFoundException("Attribute '" + attribute
+ "' does not exists");
}
}

/*
* (non-Javadoc)
*
* @see javax.management.DynamicMBean#getAttributes(java.lang.String[])
*/

public synchronized AttributeList getAttributes(String[] attributes) {
AttributeList list = new AttributeList();
for (String name : attributes) {
String value = managedBootstrap.getComponentPropertiesManager()
.getProperties().getProperty(name);
if (value != null
&& !value
.startsWith(ComponentPropertiesManager.MANAGED_METHOD_PREFIX))
list.add(new Attribute(name, value));
}
return list;
}

/*
* (non-Javadoc)
*
* @see javax.management.DynamicMBean#setAttribute(javax.management.Attribute)
*/

public synchronized void setAttribute(Attribute attribute)
throws AttributeNotFoundException, InvalidAttributeValueException,
MBeanException, ReflectionException {
String name = attribute.getName();
if (managedBootstrap.getComponentPropertiesManager().getProperties()
.getProperty(name) == null) {
throw new AttributeNotFoundException(name);
}

Object value = attribute.getValue();
if (!(value instanceof String)) {
throw new InvalidAttributeValueException(
"Attribute value not a string: " + value);
}

// set the property and save the properties file
managedBootstrap.getComponentPropertiesManager().getProperties()
.setProperty(name, (String) value);
try {
save();
} catch (IOException e) {
throw new MBeanException(e);
}
}

/*
* (non-Javadoc)
*
* @see javax.management.DynamicMBean#setAttributes(javax.management.AttributeList)
*/

public synchronized AttributeList setAttributes(AttributeList list) {
AttributeList result = new AttributeList();

for (Object object : list) {
Attribute attr = (Attribute) object;
String name = attr.getName();
Object value = attr.getValue();
if (managedBootstrap.getComponentPropertiesManager()
.getProperties().getProperty(name) != null
&& value instanceof String) {
managedBootstrap.getComponentPropertiesManager()
.getProperties().setProperty(name, (String) value);
result.add(new Attribute(name, value));
}
}

try {
save();
} catch (IOException e) {
return new AttributeList();
}
return result;
}

/*
* (non-Javadoc)
*
* @see javax.management.DynamicMBean#getMBeanInfo()
*/

public synchronized MBeanInfo getMBeanInfo() {
// get the attributes
MBeanAttributeInfo[] attrs = getAttributesInfos();
// get the operations
MBeanOperationInfo[] opps = getOperationsInfos();

// create MBeanInfo with no constructors and no notifications
return new MBeanInfo(this.getClass().getName(),
"Property Manager MBean", attrs, null, opps, null);
}

/**
* Dynamically get the operations for the MBean. The operations are defined
* in the properties manager with a special prefix.
*
* @return
*/

protected MBeanOperationInfo[] getOperationsInfos() {
List<String> methods = managedBootstrap.getComponentPropertiesManager()
.getExposedMethodNames();
MBeanOperationInfo[] result = null;

List<MBeanOperationInfo> operations = new ArrayList<MBeanOperationInfo>();
Method methodList[] = managedBootstrap.getClass().getMethods();

for (int i = 0; i < methodList.length; i++) {
Method method = methodList[i];
String name = method.getName();

// add method if it has been defined by the user
if (methods.contains(name)) {
MBeanOperationInfo oper = new MBeanOperationInfo(
"Operation description", method);
operations.add(oper);
}
}

result = new MBeanOperationInfo[operations.size()];
operations.toArray(result);

return result;
}

/**
* Dynamically get attributes for the MBean. The attributes are the ones
* from the properties file.
*
* @return
*/

protected MBeanAttributeInfo[] getAttributesInfos() {
// get the attributes names as sorted strings
Set<String> attributeKeys = managedBootstrap
.getComponentPropertiesManager().getExposedAttributeKeys();

// build the MBeanAttributeInfo
MBeanAttributeInfo[] attrs = new MBeanAttributeInfo[attributeKeys
.size()];
Iterator<String> it = attributeKeys.iterator();
for (int i = 0; i < attrs.length; i++) {
String name = it.next();
attrs[i] = new MBeanAttributeInfo(name, "java.lang.String",
"Property " + name, true, true, false);
}
return attrs;
}

/*
* (non-Javadoc)
*
* @see javax.management.DynamicMBean#invoke(java.lang.String,
* java.lang.Object[], java.lang.String[])
*/

public Object invoke(String actionName, Object[] params, String[] signature)
throws MBeanException, ReflectionException {
Object result = null;

final Class objClass = managedBootstrap.getClass();
final ClassLoader loader = objClass.getClassLoader();
final Class[] parameters = ((signature == null) ? null
: findSignatureClasses(signature, loader));

// Query the metadata service to get the right method
//
Method method = null;
try {
method = objClass.getMethod(actionName, parameters);
} catch (Exception e) {
}

if (method == null) {
throw new ReflectionException(
new NoSuchMethodException(actionName),
"The operation with name " + actionName + " could not be found");
}

try {
// invoke method
result = method.invoke(managedBootstrap, params);
} catch (IllegalAccessException e) {
throw new ReflectionException(e, "IllegalAccessException"
+ " occured trying to invoke operation " + actionName);
} catch (RuntimeException e) {
throw new RuntimeOperationsException(e, "RuntimeException"
+ " occured trying to invoke operation " + actionName);
} catch (InvocationTargetException e) {
throw new MBeanException(e, "Exception thrown in operation "
+ actionName);
}
return result;
}

/**
* Find the classes of the signature
*
* @param signature
* @param loader
* @return
* @throws ReflectionException
*/

private Class[] findSignatureClasses(String signature[], ClassLoader loader)
throws ReflectionException {
if (signature == null)
return null;

final int length = signature.length;
final Class tab[] = new Class[length];

if (length == 0)
return tab;

try {
for (int i = 0; i < length; i++) {

// try to get the primitive class
final Class primCla = (Class) primitiveClasses
.get(signature[i]);
if (primCla != null) {
tab[i] = primCla;
} else {
// try to get the class if not primitive one
tab[i] = Class.forName(signature[i], false, loader);
}
}
} catch (ClassNotFoundException e) {
throw new ReflectionException(e,
"The parameter class could not be found");
} catch (RuntimeException e) {
throw e;
}
return tab;
}

/**
* Save the properties to a file
*
* @throws IOException
*/

private void save() throws IOException {
managedBootstrap.getComponentPropertiesManager().save();
}


About

I am a software engineer and community manager on the open source PEtALS ESB project at eBM WebSourcing.
You can get this article as PDF file on my scribd space or on my work blog.

January 27, 2008 11:50 PM

PEtALS 1.2 and Axis2BC new features

PEtALS 1.2 is finally out (http://petals.objectweb.org ).
This new release introduces lot of new features and improvements like:

As I have worked again on the Axis2 binding component (Axis2BC), here are some new improvements on this component:
How does SOAP attachment works?
As simple as:
  1. For incoming messages, all the SOAP attachments are placed as JBI ones
  2. For outgoing messages, all the JBI attachments are placed as SOAP ones
With Axis2, two types of attachments are possible, MTOM(Message Transmission Optimization Mechanism) and SWA (SOAP With Attachments).
Both of them allows to handle large amounts of binary data. More explanations are available on the Web...
In the Axis2BC we use the MTOM approach.

Adding SOAP attachments is as simple as (code snippet from org.objectweb.petals.binding.axis2.listener.jbi.JBIListener class):
    protected OMElement createSOAPMessage(NormalizedMessage nm,
        ServiceClient client) throws XMLStreamException,
        FactoryConfigurationError, PEtALSComponentSDKException {

        // create the root element
        OMFactory fac = OMAbstractFactory.getOMFactory();
        Source body = nm.getContent();
        String content = SourceHelper.createString(body);
        XMLStreamReader parser = XMLInputFactory.newInstance()
            .createXMLStreamReader(new StringReader(content));
        StAXOMBuilder builder = new StAXOMBuilder(parser);

        OMElement document = builder.getDocumentElement();

        // add attachments if any
        if (nm.getAttachmentNames().size() > 0) {
            // enable MTOM
            client.getOptions().setProperty(
                Constants.Configuration.ENABLE_MTOM, Constants.VALUE_TRUE);

            // Add JBI attachments to the document element
            Set names = nm.getAttachmentNames();
            for (Object key : names) {
                String name = (String) key;
                DataHandler attachment = nm.getAttachment(name);
                OMText attach = fac.createOMText(attachment, true);
                document.addChild(attach);
            }
        }

        return document;
    }

And getting SOAP attachments from SOAP message (code snippet from org.objectweb.petals.binding.axis2.listener.soap.PetalsReceiver class) :
    private void copySOAPAttachmentsToJBI(MessageContext messageContext,
        NormalizedMessage nm) throws MessagingException {

        if (nm != null && messageContext != null) {
            Attachments attachments = messageContext.getAttachmentMap();
            if (attachments != null) {
                Set set = attachments.getContentIDSet();
                for (Object object : set) {
                    String id = (String) object;
                    DataHandler dh = attachments.getDataHandler(id);
                    nm.addAttachment(id, dh);
                }
            }
        }
    }

A simple test scenario
A simple scenario to test the SOAP attachments with PEtALS is described below. We use the PEtALS sample client to send data to a service that will write it into a directory. In order to use the Axis2 binding component, it is placed between the client and the targeted endpoint. The 'workflow' is:
  1. Send data and attachments to Axis2BC provided endpoint. This endpoint provides access to an external web service.
  2. The Axis2BC takes all the data from the incoming JBI message and put it into the SOAP message
  3. The Axis2BC sends the SOAP message to the external web service
  4. Axis2BC is also configured to handle external on the address previously invoked. It consumes an endpoint provided by the File Transfer binding component (FTBC)
  5. Axis2BC handle the incoming SOAP message and put all the data (and attachments) into a new JBI message
  6. The JBI message is sent to the FTBC endpoint
  7. The FTBC endpoint receives the JBI message and write all the data to files
  8. Response is sent to client...

All the needed service units are available on the PEtALS use cases section here.

This blog entry is also available at http://docs.google.com/Doc?id=dcrqrprg_27hnpbfk


January 27, 2008 11:50 PM

Install configure and use a corporate maven repository and a maven proxy

Maven proxy is a nice tool but documentation available on the web is not...
This blog entry describes how to install, configure and use the maven-proxy. It also defines how to create a corporate maven repository.

Maven2 installation

Binary installation

Download the latest binary version of maven (http://maven.apache.org ) and as root:
cd /usr/share
tar zxvf maven-x.y.z-bin.tar.gz
ln -s maven-x.y.z maven2

Configuration

Add environment variables to the /etc/profile file (or in your .bashrc if you want)
M2_HOME=/usr/share/maven2
MAVEN_OPTS=-Xmx256M
PATH=$PATH:$M2_HOME/bin
export M2_HOME
export MAVEN_OPTS
export PATH

Create a deployer user

This user will be used to deploy new artifacts in maven repositories.
mkdir /home/maven
useradd -g buildauto -d /home/maven maven
passwd maven
chown -R maven:buildauto /home/maven

Create Maven2 corporate repositories

We create two repositories, one for the the artifacts that can not be installed for licence reasons and the other for the artifacts snapshots that will only be accessible directly. You have to install apache first(out of scope of this blog entry, tell your system admin to install it or ask google how to do it if you don't know how).

Directories

As root:
mkdir /var/lib/m2-repo
mkdir /var/lib/m2-repo-snapshots
chown -R maven:buildauto /var/lib/m2-repo /var/lib/m2-repo-snapshots

Create symbolic links to be abble to access these repositories with http. If apache handle directories in /var/www, simply create the links:
ln -s /var/lib/m2-repo /var/www/maven2
ln -s /var/lib/m2-repo-snapshots /var/www/maven2-snapshots

Repositories are now accessible at addresses http://repo_host/maven2 and http://repo_host/maven2_snapshots.

How to install artifacts

To install an artifact in the repository, use maven2 command:
mvn deploy:deploy-file
      -Durl=scp://repo_host:/var/lib/m2-repo
      -DrepositoryId=corpo-maven-repository
      -Dpackaging=<packaging>
      -DgroupId=<groupId>
      -DartifactId=<artifactId>
      -Dversion=<version>
      -Dfile=<file>

or this one if you already have the pom of the artifact:
mvn deploy:deploy-file
    -Durl=scp://repo_host:/var/lib/m2-repo
    -DrepositoryId=corpo-maven-repository
    -DpomFile=<pomfile>
    -Dfile=<jarfile>


You can specify the repositoryId in your maven2 configuration file to avoid entering user name and password each time (in $M2_HOME/conf/settings.xml):
<server>
   <id>corpo-maven-repository</id>
   <username>maven</username>
   <password>xxx</password>
</server>

Maven proxy installation

Download the maven-proxy standalone : http://maven-proxy.codehaus.org

Connect your maven server as root and enter these commands:
cd /usr/share
tar zxvf maven-proxy-standalone-x.y.z.tar.gz
mkdir maven-proxy
cd maven-proxy
ln -s ../maven-proxy-x.y.z/maven-proxy-standalone-x.y.z-app.jar maven-proxy-standalone-app.jar

Next we need to create the cache directory (the proxy will download the required files here)
mkdir /var/cache/maven-proxy

Copy the maven properties file in /etc/maven/maven-proxy.properties. You can download a sample of this file from the maven-proxy website.
In this file, you are going to specify the repositories you want to access through the proxy. For example:

################ GLOBAL SETTINGS
# This is where maven-proxy stores files it has downloaded
repo.local.store=/var/cache/maven-proxy
...
################ SNAPSHOT HANDLING
#If you want the proxy to look for newer snapshots, set to true
snapshot.update=false
...
################# REPOSITORIES
#This is not just a hack, it specifies the order repositories should be checked
#Note that the proxy adds a "/" which is why the urls aren't suffixed with a "/"
repo.list=local-repo,www-ibiblio-org
repo.local-repo.url=file:////var/lib/m2-repo
repo.local-repo.description=My corpo - Maven2 Repository
repo.local-repo.copy=false
repo.local-repo.hardfail=true
repo.local-repo.cache.period=0
#www.ibiblio.org
repo.www-ibiblio-org.url=http://www.ibiblio.org/maven2
repo.www-ibiblio-org.description=www.ibiblio.org
repo.www-ibiblio-org.hardfail=true
repo.www-ibiblio-org.cache.period=3600
repo.www-ibiblio-org.cache.failures=true
#other repo
...

If you want to add logs, you can modify the log4j properties file in the proxy jar file to add logs (extract and jar it again):
# Set root logger level to DEBUG
log4j.rootLogger=DEBUG,CONSOLE,R
# ConsoleAppender.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
# Console PatternLayout.
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d [%-5p] %-20c{3} %x - %m%n
log4j.logger.org.mortbay=WARN
log4j.logger.httpclient.wire=INFO
log4j.logger.org.apache.commons.httpclient=INFO
log4j.logger.org.apache.jasper=INFO
# File appender
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=/var/log/maven-proxy.log
log4j.appender.R.MaxFileSize=100KB
# Keep one backup file
log4j.appender.R.MaxBackupIndex=1
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n

Proxy daemon

Installing the proxy as daemon in /etc/init.d/maven-proxy
#! /bin/sh
set -e
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DESC="Maven Proxy"
NAME=maven-proxy
JAVA_HOME=/home/dev/bin/java
DAEMON=$JAVA_HOME/bin/java
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
MAVENPROXY_HOME=/usr/share/$NAME
MAVENPROXY_JAR=$MAVENPROXY_HOME/maven-proxy-standalone-app.jar
# Gracefully exit if the package has been removed.
test -r $MAVENPROXY_JAR || exit 0
# Function that starts the daemon/service.
d_start() {
# We change dir to /var/log, because Velocimacro logfile is created in the current directory
   start-stop-daemon --chdir /var/log --start --background --quiet \
                     --pidfile $PIDFILE --make-pidfile --exec $DAEMON -- -jar $MAVENPROXY_JAR \
                                                        /etc/maven-proxy/maven-proxy.properties
}
# Function that stops the daemon/service.
d_stop() {
   start-stop-daemon --stop --quiet --pidfile $PIDFILE --signal TERM
}
# Function that sends a SIGHUP to the daemon/service.
d_reload() {
   start-stop-daemon --stop --quiet --pidfile $PIDFILE --signal 1
}
case "$1" in
  start)
   echo -n "Starting $DESC: $NAME"
   d_start
   echo "."
   ;;
  stop)
   echo -n "Stopping $DESC: $NAME"
   d_stop
   echo "."
   ;;
  restart|force-reload)
   #
   # If the "reload" option is implemented, move the "force-reload"
   # option to the "reload" entry above. If not, "force-reload" is
   # just the same as "restart".
   #
   echo -n "Restarting $DESC: $NAME"
   d_stop
   sleep 1
   d_start
   echo "."
   ;;
  *)
   echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
   exit 1
   ;;
esac
exit 0

Create the links for host startup:
ln -s ../init.d/maven-proxy /etc/rc3.d/S22maven-proxy
ln -s ../init.d/maven-proxy /etc/rc4.d/S22maven-proxy
ln -s ../init.d/maven-proxy /etc/rc5.d/S22maven-proxy

And start the proxy as root like this
/etc/init.d/maven-proxy start

Use the proxy

Now that the environment has been setted up, you can use it for your developments.

Configuration file

You have to tell maven that you want it uses the proxy. To do this, you must add the settings.xml file to your local repository (in $HOME/.m2/).
<settings>
        <profiles>
                <profile>
                        <id>default-profile</id>
                        <activation>
                                <activeByDefault>TRUE</activeByDefault>
                        </activation>
                        <repositories>
                                <repository>
                                        <id>myproject-repository-repohost</id>
                                        <name>repohost Repo</name>
                                        <url>http://192.168.1.230:9999/repository/</url>
                                        <snapshots>
                                                <enabled>TRUE</enabled>
                                        </snapshots>
                                        <releases>
                                                <enabled>TRUE</enabled>
                                        </releases>
                                </repository>
                        </repositories>
                        <pluginRepositories>
                                <pluginRepository>
                                        <id>myproject-repository-repohost</id>
                                        <name>repohost Repo</name>
                                        <url>http://192.168.1.230:9999/repository/</url>
                                        <snapshots>
                                                <enabled>TRUE</enabled>
                                        </snapshots>
                                        <releases>
                                                <enabled>TRUE</enabled>
                                        </releases>
                                </pluginRepository>
                        </pluginRepositories>
                </profile>
        </profiles>
</settings>

Now you can remove all the repositories from your pom files and let maven get artifacts from the proxy.

January 27, 2008 11:50 PM

The PEtALS v1.1 Axis2 binding component

PEtALS 1.1 is finally out with lot of new features and improvements.
I have done many changes to the Axis2 binding component (Axis2BC) which is currently based on Axis2 v1.1.1.
This binding component is used to handle incoming and outgoing SOAP requests from/to the JBI container. It uses the PEtALS Component Development Kit (CDK) and offers lot of new features in its current 1.1 version.

The current article details the main features of the BC and also introduces the methodology used to offer these features.

How to embed a Jetty Server ?

As a binding component, the SOAP have to be able to handle incoming SOAP requests. The choice of using a Jetty server to handle incoming SOAP requests comes from:
  1. The simple server provided with Axis has poor performances. This server was used on the previous version of the BC. The performance study I have made shows that handling web service calls into a dedicated server is better.
  2. Jetty is easily embeddable (Tomcat is not as easy as Jetty)
  3. Servlets can be deployed easily on Jetty

Like mentioned above, embedding a Jetty server is quite simple. You also have to create a new instance of the server like this (snippet from class org.objectweb.petals.binding.axis2.listener.soap.AxisJettyServer):

public AxisJettyServer(ConfigurationContext configurationContext, int port) throws AxisFault {
this.port = port;
this.configurationContext = configurationContext;
this.server = new Server(this.port);

// create context handlers
ContextHandlerCollection contexts = new ContextHandlerCollection();
server.setHandler(contexts);

// create the axis context
Context axis2 = new Context(contexts, "/axis2", Context.SESSIONS);

// create servlet holders
ServletHolder axisServlet = new ServletHolder(new AxisJettyServlet(
configurationContext));
axisServlet.setName("AxisServlet");
axisServlet.setInitOrder(1);

// do servlet mappings
axis2.addServlet(axisServlet, "/services/*");
// axis2.addServlet(axisRESTServlet, "/rest/*");
axis2.addServlet(axisServlet, "/servlet/AxisServlet");
// axis2.addServlet(axisAdminServlet, "/axis2-admin/*");

// AXIS
ListenerManager listenerManager = configurationContext
.getListenerManager();
TransportInDescription trsIn = new TransportInDescription(new QName(
Constants.TRANSPORT_HTTP));
trsIn.setReceiver(this);
if (listenerManager == null) {
listenerManager = new ListenerManager();
listenerManager.init(configurationContext);
}
listenerManager.addListener(trsIn, true);
}

In the above code, we create the context and we register a the servlet AxisJettyServlet that will be used to handle incoming SOAP requests.
To start and stop the server you have simply to call the start and stop method like this:

public void start() throws AxisFault {
// start the jetty server in a separate thread
Runnable httpListenerRunnable = new Runnable() {
public void run() {
try {
server.start();
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
};
Thread httpThread = new Thread(httpListenerRunnable,
"Jetty started Thread");

try {
httpThread.start();
httpThread.join();
} catch (InterruptedException e) {
throw new AxisFault(e.getMessage());
} catch (Exception e) {
throw new AxisFault(e.getMessage());
}
}

Even if embedding Jetty was quite simple, tuning Axis to work like we want it works in the JBI environment was not so simple. I will discuss about this later on this post.

Registering new services

To create and register the new service, follow the steps:
  1. Create a new AxisService (org.apache.axis2.description.AxisService)
  2. Add parameters such as document definition for example (not used like this in the BC)
  3. Register it into the axis configuration (org.apache.axis2.engine.AxisConfiguration)

The code snippet above is taken from the SUListener used in the Axis2BC:

AxisService axisService = new AxisService(endPointName);
axisService.setTargetNamespace(serviceQName.getNamespaceURI());
axisService.setEndpoint(consumedEndpoint);

axisService.addParameter(new Parameter(Constants.SERVICE_CLASS, "PetalsReceiver"));

// add parameter to handle ?wsdl requests
Parameter useOriginalwsdl = new Parameter("useOriginalwsdl", "true");
axisService.addParameter(useOriginalwsdl);

ServiceEndpoint endpoint = componentContext.getEndpoint(serviceQName, consumedEndpoint);
if (endpoint != null) {
Definition def = null;
Document document = componentContext.getEndpointDescriptor(endpoint);
if (document != null) {
try {
def = WSDLHelper.createDefinitionFromDocument(document);
} catch (WSDLException e) {
logger.log(Level.WARNING, "WSDL Definition has not been initialized");
}
}

Parameter defParam = new Parameter(WSDLConstants.WSDL_4_J_DEFINITION, def);
axisService.addParameter(defParam);

} else {
logger.log(Level.WARNING, "Enpoint " + consumedEndpoint
+ " has not been found, service "
+ axisService.getName() + " registered");
}

// add service
axisConfig.addService(axisService);

Handling incoming calls

As mentioned above, handling incoming SOAP calls is done with the Axis servlet deployed on the Jetty server. When the servlet handle the HTTP request, lot of work processing and mapping is done by the Axis engine. To be able to transform and send the data from Axis to JBI, we have developed and added a special Axis Dispatcher (org.objectweb.petals.binding.axis2.listener.soap.PetalsDispatcher).
This is possible since Axis is an extensible messaging engine. Simply by adding our dispatcher to the axis2.xml configuration file (and configuring it during the BC initialization), the SOAP message will be transformed into a JBI one and then sent to the linked JBI endpoint.

To create a dispatcher, simply extends the abstract dispatcher class:
org.apache.axis2.engine.AbstractDispatcher

Modify the axis2 configuration file by adding you dispatcher (from axis2.xml) :

...


class="org.objectweb.petals.binding.axis2.listener.soap.PetalsDispatcher">


...

...


Handling outgoing calls

This operation was very simple. Since the BC uses the CDK, this CDK provides abstract class to extend to handle incoming JBI message.
In the PEtALS CDK, we use the JBIListener (org.objectweb.petals.component.common.bc.JBIListener). The method to implement is:

boolean onJBIMessage(String address, MessageExchangeWrapper exchange,
Extensions extensions) throws HandlingException;

The only thing to do in the implementation is to create a SOAP message from the JBI one and then to send it to the external web service using the Axis2 API.

SOAP with attachments

One cool feature that is provided by Axis is the capability to handle SOAP attachments with two methods:
  1. MTOM : Message Transmission Optimization Mechanism

  2. SWA : SOAP with attachments

To use the SOAP attachments, you need to enable one of the previous mode (if both are enabled, MTOM will get priority over SwA).
To enable MTOM, you can:

The SwA will be enabled like this:

SOAP with attachments will be provided soon in the Axis2BC probably with the MTOM method.

Getting the service description

After all the previous modifications on the Axis behaviour, and in addition of the JBI container, getting the WSDL description of a provided service was not so simple. After investigations I discovered that the mechanism is very different from the one that we was using with Axis1.
To be able to provide the WSDL description that is stored in the JBI container the simplest solution was to extends the AxisService class and to override the printWSDL methods. In the overridden methods, we get the WSDL description from the JBI container through the component context. In this case, the WSDL description is always up to date when a component is removed from the container and installed again with a brand new description.

Proxy enabled

The Axis2BC is proxy compliant. It just have to be configured with the service unit. To do so, simply add proxy settings in the service unit like this:




...

?
hostname
port
user
password
domain
?





January 27, 2008 11:50 PM

January 25, 2008

Ludovic Dubost

Rapport Attali

Avant-hier, j’ai passé un peu de temps à lire le rapport Attali.

Un débat est en cours au sujet des propositions sur l’Open-Source. L’AFDEL a réagit violement dans un ...

January 25, 2008 04:40 PM

January 21, 2008

Pierre-Yves Gibello

Default face

La Foulée Blanche en caméra embarquée !

Fervent adepte du ski de fond, j'ai eu récemment l'idée saugrenue de filmer de l'intérieur un départ de course longue distance. Evidemment, pas question de s'encombrer d'un matériel lourd, ni d'ajouter aux contraintes de la course celles de la prise de vue...
J'ai donc choisi de "scotcher" (velcro, en fait) une mini-caméra derrière ma ceinture porte-bidon : en l'occurrence, il s'agit d'une "FlyCam One V2", petit appareil de 40 grammes équipé d'une SD Card et destiné à l'origine au modélisme aérien.
Premier test - peu concluant- au marathon de Bessans : je n'ai filmé que le ciel ! J'ai également découvert que ma caméra ne supportait guère le froid (je scotche donc une chaufferette à mains dessus), et que l'autonomie batterie était fort limitée (c'est le prix de la légèreté).

C'est donc fort de ces expériences que je me suis attelé à filmer le départ de la Foulée Blanche 2008 (42km, style libre), ce 20 Janvier à Autrans : résultat, 7 minutes de vidéo brouillonne et aux couleurs fantaisistes, mais quand même, on y est... sur une fantastique "neige à chrono", l'ambiance des 3 dernières minutes de film est même assez électrique !

Mais trève de bavardages : allez donc voir le résultat sur DailyMotion (lien permanent : http://www.dailymotion.com/video/x44b76_foulee-blanche-2008_sport), en espérant que ce genre d'idée fasse des émules... et attire des skieurs vers nos belles pistes de fond !


Foulée Blanche 2008

January 21, 2008 02:15 PM

January 17, 2008

Orbeon

Default face

Bad forms, part II

Continental Logo

I recently booked a flight on the Continental web site. I knew approximately the flight I wanted to book, so dug right away into the search to select it. I encountered the following issues:

Now let’s say the developers of the Continental web site decide to switch to Orbeon Forms and XForms for the next version of the web site:

And this is all interactive too, meaning that the user doesn’t need to wait one minute to know that some fields are missing or incorrect.

January 17, 2008 02:24 AM

January 14, 2008

Valerio Schiavoni

Default face

www.macbookair.com redirects to apple.com

The url: http://www.macbookair.com now redirects to:

http://www.apple.com/?Will+We+see+a+MacBookAir+on+Tuesday?

The hype is mounting...

January 14, 2008 11:36 PM

MacBook Air leaked?

Let's face it yourself : http://images.worldofapple.com/87a7fr4.gif
 

January 14, 2008 10:58 PM

January 13, 2008

Jéremi Joslin

Anti portabilité des réseaux sociaux.

Quelques mois de ça, je parlais de la portabilité des réseaux sociaux. Je n’ai malheuresement pas continué ma suite d’article prévu. Depuis cet article, pas mal de choses se sont passé, en particulier les groupes de travail Data portability et Diso .

Après l’histoire de Robert Scoble se faisant fermer son compte pour avoir essayé d’exporter les emails de ses contacts dans Plaxo, la portabilité des réseaux sociaux a fait beaucoup de bruits. Bob Backley du Burton Group trouve cela normal:

"Even the fact of your relationship with Scoble is not Scoble’s property, it is common property, like the kids in a joint custody arrangement. Both you and Scoble are obligated by the laws of relation to treat the fact that you have a relationship, and also the details of the relationship, according to certain understandings and social conventions. If you don’t believe this, meditate on whether you think it would be OK for adultfriendfinder.com, match.com, and linkedin to share friend lists. The information Scoble tried to take out of Facebook is NOT Scoble’s property; it is relationship information. Scoble is not free to do whatever he pleases with relationship information; if he violates social understandings and conventions by disclosing the existence of or certain information about his relationship with you in the wrong context, he may embarrass or endanger you, and he will certainly endanger the relationship."

D’un côté je partage l’avis que la relation qui me lit à quelqu’un n’appartient pas qu’a moi, mais elle est partagé avec l’autre personne. Mais elle n’appartient pas à Facebook non plus. Facebook est en quelque sorte le tierce de confiance dans ma relation avec mes amis.

L’idée que je me fais de la portabilité des réseaux sociaux n’est pas de répliquer 1:1 ma liste d’amis sur Facebook et sur Linked’In et encore moins créer une relation bilatérale (à la différence de la relation de fan qui est unilatéral en général, et qui existe par exemple sur pownce) avec un ami de Linked’In sur facebook sans son autorisation. Le fait de rendre les réseaux portable ne veut pas dire non plus que je vais avoir les mêmes amis sur tous les réseaux, mais plutôt d’avoir la possibilité d’extraire ma liste d’amis d’un réseau social, de sélectionner ceux que je souhaite synchroniser avec mon autre réseau social. Il faut donc une application tierce dont le seul objectif est de gérer votre liste de contact et les relations avec les gens. C’est elle qui gère l’intermédiaire entre les différents « walled garden ».

Je pense qu’il ne serait pas très difficile de prototyper une application de ce style.

January 13, 2008 04:28 PM

January 10, 2008

Jéremi Joslin

video d’eXo Platform @ openCoffee

eXo @ openCoffee

Enregistrè à l’OpenCoffee Club de Paris, le 3 janvier 2008. Je parle des nouvelles applications qui vont arriver bientôt :)

merci à Stéphane Enilorac de moovement.fr pour la video.

January 10, 2008 01:30 PM

Christophe Hamerling

Default face

Too many open files IOException with large number of Axis2 Servic

This is a problem we met in the PEtALS SOAP Binding Component with large number of Axis2 Service Clients.
In this case, this error happens when too many sockets are open ant are waiting to be closed. Even if I have found some JIRAs about this problem and possible solutions, the only one which work for us is to cleanup the connection after each service call.
It is done like this :

...

ServiceClient client = new ServiceClient(null, service);

Options options = new Options();

...

options.setCallTransportCleanup(true);

client.setOptions(options);


OMElement outBodyElement = null;

try {

outBodyElement = serviceClient.sendReceive(soapAction, inBodyElement);

} catch (AxisFault e) {

throw e;

}



After 10 minutes test with 200 threads creating 'one shot ' ServiceClient and almost 275000 service calls, all worked fine.

January 10, 2008 09:00 AM

January 09, 2008

Valerio Schiavoni

Default face

Removing object methods in Ruby

Ruby provides a built-in mixin facility which turns out to be very useful for meta-programming issues. As you might know, having an object extending a module results in the original object to provide all methods of the module.

Something like:

class Server
end
module Print
  def print
    puts 'hello'
  end
end
s = Server.new
#mixing in printing capabilities
s.extend(Print)
s.print

will safely result in printing 'hello'. But how can we remove it back again, so that the print method is no longer availble? Well, here's the trick:

Print.send :remove_method, :print
s.print

if you run the code above, you should see something like :

hello
misc.rb:19: private method `print' called for # (NoMethodError)

This has a drawback: creating a new instance of Server, and letting it extend the Print module won't be enough to have back a printer-aware server...I still have to find out how to remove the method from an instance object, and from it alone, without impacting on other (possibly not existent yet) instances.

January 09, 2008 10:02 PM

January 08, 2008

Orbeon

Default face

Yahoo! goes XForms

Yahoo! Blueprint

Yahoo! today announced a new mobile platform called “Mobile Widgets”. The amazing part is that the language used to describe widgets, called Blueprint, is based on XForms:

Much of Blueprint’s philosophy and syntax comes from XForms. We opted for a full declarative language because it was the only way we could effectively run on the wide range of devices out there, some of which have no scripting at all. By using declarative syntax, we can encapsulate and hide the scripting specifics. In some cases, the code could run on the phone, in other case, such as XHTML, we can put the logic on our servers. It’s the perfect way to deal with the various environments and their capabilities.

The Blueprint Philosophy and roadmap highlights the benefits of declarative vs. imperative, “because it was the only way we could effectively run on the wide range of devices out there, some of which have no scripting at all”. For now, only very basic XForms constructs are supported, but “In our second release of the Blueprint language you’ll be able to take full advantage of the power of XForms-style MVC programming”.

Although Orbeon does not particularly focuses on mobile devices, this philosophy is entirely in line with our transformations- and Ajax-based approach to deliver XForms everywhere (in our case to mainstream browsers). It is excellent news that a company like Yahoo! not only recognizes the benefits of the XForms approach, but also decides to leverage the standard instead of reinventing the wheel (like Google did with their Google Mashup Editor, which looks very much like an incompatible clone of XForms).

In short this is extremely positive for the XForms community. We can only hope that Blueprint lives up to its promises.

January 08, 2008 03:57 PM

Valerio Schiavoni

Default face

SCOrWare website public

In case you haven't noticed, the official website for the SCOrWare project went public some time ago now.

The SCOrWare project aims at providing an open source implementation of the recent Service Component Architecture (SCA) specifications

January 08, 2008 01:44 PM

January 07, 2008

Stéphane Traumat

Déménagement du blog de scub :)

Afin de faciliter la vie de nos lecteurs, nous avons décidé de faire un seul et unique blog pour tous les employés de Scub. Vous n'aurez donc plus qu'à vous connecter à cette adresse pour voir les posts de tous les gens qui font Scub !

Adresse du blog : http://www.scub.net/blog

January 07, 2008 05:20 PM

December 19, 2007

Valerio Schiavoni

Default face

Java 6 DP8 for Leopard: cool, but no Eclipse for now.

Ok, so Apple is still working on it. Nice to know.

Now, after the first 5 seconds of joy, let's calm down. Go and read the release note (you need to have an ADC free account,  sorry, i can't copy/paste it, it's under NDA).

But....well...it's a 64bit-only cpu enabled version ! This wouldn't bit a major problem, if not that Eclipse can't work ! At the moment, there's no SWT version compatible. Quoting an Apple engineer:

"The SWT is compiled for 32-bit Intel only, and even if you did try to rebuild it yourself, most of it won't build because the Carbon calls they use aren't available in 64-bit."

 

Volunteers go here: http://www.eclipse.org/swt


December 19, 2007 02:08 PM

December 17, 2007

JOnAS Team

JOnAS 5.0.0 Release Candidate

Hi JOnAS Enthusiasts !

All the JOnAS developers have spend a very long time (especially this week for the release) to offer to you this year‘s Xmas version of JOnAS !

We‘re very pleased to announce the availability of the new JOnAS release. This is the first Release Candidate (RC1) of the JOnAS 5.0 serie.

This version is special because it‘s our first OSGi release! It means that there was a lot of code refactoring in order to add dynamism at the heart of the application server.

If you want to see more about JOnAS 5.0.0 Release Candidate take a look at the New and noteworthy and check out the Getting Started (for JOnAS/OSGi).

Packages are downloadables from the OW2 forge.

JOnAS 5.0.0 is also available in its classic personnality (no OSGi, old style JONAS_ROOT).

Now, this release is in your hands: provide us some feedback through the mailing lists, fill the bug tracker with any issue you may find, …

Enjoy, and stay tunned for future announcements.

Guillaume
on behalf on the JOnAS team

December 17, 2007 10:40 PM

Valerio Schiavoni

Default face

Rails and iPhone: step 1

I finally decided to start working with Ruby on Rails. After the scaffolding examples and some experience with the whole ruby thing, things started to become interesting, and I start feeling good about ruby and bad about java alt=title=":-)" />

So, the first thing I decided to implement is a simple register/login system, quite common in nowadays web application. I used the restful_authentication plugin, which almost worked out of the box for me. Problems came from some changes between rails 1.2.3 and the latest 2.0.1, causing some apparent conflict in the routes.rb configuration file.

Then, I discovered a nice little application called iPhoney, to test the look&feel; of any web application as if the web client is the iphone one.

Here's the result:

iphoney
 

Now I'll go on with some more usefull business logic. 

December 17, 2007 12:26 PM

December 14, 2007

Valerio Schiavoni

Default face

how to add super-priviliged user to mysql

That's almost a note for my self:

GRANT ALL privileges ON . to 'username'@'localhost' identified by 'pwd' with gr