Planet ObjectWeb
January 29, 2008
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:
-
When this feature is enabled, an open XForms page regularly pings the server through Ajax to keep the current session alive.
-
The ping delay is automatically computed based on the server’s session timeout. The client pings the server at 80% of the session expiration time after the last interaction with the server.
-
We are careful not to hit the XForms engine too much, in fact we do a very limited amount of work on the server for each ping, so they should run fast.
-
XForms state information for pages hit with the heartbeat just migrates to the disk store over time if RAM is used by other pages, so keeping even large numbers of pages open should not have any negative impact on server RAM.
-
When a user gets back to using the page, state information migrates back from disk to RAM, and the page will be live again.
-
Sessions do eventually expire as nobody keeps a browser open forever.
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
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
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 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
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
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...
Configuration seems very intuitive... Going to test it for PEtALS project...
January 27, 2008 11:50 PM
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 :- The PEtALS kernel 2.0
- A new Web Console for monitoring and administration
- The Component Development Kit 3.0 : Library and tools for easily and rapidly create JBI compliant components.
- A collection of JBI compliant components (including new ones like XMPP, HTTP binding components, EIP, RMI Service Engines)
- An Eclipse plugin for JBI artifacts development and administration
- Docbook based documentation
- Brand new website & logo
Complete release note will be available on the PEtALS Website.
January 27, 2008 11:50 PM
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
PEtALS 2.0 is on the way. The beta version will be out in few weeks with cool features :
- Eclipse plugin for development, test and integration
- Multi-transporter with Dream for synchronous communication and Joram for asynchronous communication
- RMI client for direct access to the bus API
- UDDI registry Service Engine
- EIP Service Engine
- Enhanced SOAP Binding Component
- Component Development Kit 2.0
- JBOSS integration
- Failure management / load balancing
- Large deployment with Fractal Deployment Framework
- Performance optimisations
- Enhancements in monitoring tool
- New docbook documentation
January 27, 2008 11:50 PM
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 open,source,petals,jbi,soa,esb,webservices
January 27, 2008 11:50 PM
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
Core release 1.3 has been delayed and is now planned by the end of the month. Finally, we will release what we call a PEtALS Pack. This pack includes all the latest stable versions of PEtALS modules.
We have especially worked on :
A new component is available on the objectweb forge : The FTP binding component.
CDK 1.3 has been released on April the 25th 2007. It includes new configuration features through JMX during component installation.
More information on the future release note...
Main developments
Marie Sauvage (eBM WebSourcing) is working on the next version of the web administration tool. It will include lot of features to manage and administrate all the platform through a nice interface.
Nicolas Salatge (eBM WebSourcing) who has joined the developers team since a couple of months, has just completed the new PEtALS 'Fractalization'. Most of PEtALS modules are now Fractal components.
Dong Zhao has developped an OSGI version of PEtALS. This will allow to run PEtALS on any OSGI implementation (JOnAS5 and more...)
An eclipse plugin is under validation process. It will be available soon.
We are improving the CDK features again and again
- Guillaume Decarnin (Openwide) is working on csv, xquare and forward components. These components will be soon based on the new CDK.
Documentation
Others
Please do not hesitate to send your comments, ideas, and more...
Technorati Tags
news,
petals
January 27, 2008 11:50 PM
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 petals,jbi
January 27, 2008 11:50 PM
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 is finally out (http://petals.objectweb.org ).
This new release introduces lot of new features and improvements like:
- The MessageExchanges delivering mode has been improved and corrects a fault in the persistance of pending messages.
- The NormalizedMessageRouter features new routing rules : a message is firstly addressed to local a ServiceEndpoint, secondly to a distant ServiceEndpoint, and finally to a ServiceEndpoint hosted on a stopped container.
- The path of the repository where components and service assemblies are stored can be set.
- The PEtALS platform is also available as a Web Application and can be deployed on standard WebServer or J2EE Server.
- The petals-webadmin monitoring console features graphics that show instant message-traffic in a container.
- Bugs in Ant tasks have been corrected.
- ...
As I have worked again on the Axis2 binding component (Axis2BC), here are some new improvements on this component:
- List of available services available on URL/axis2/services
- SOAP attachments support
- and some bug fixes...
How does SOAP attachment works?As simple as:
- For incoming messages, all the SOAP attachments are placed as JBI ones
- 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 scenarioA 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:
- Send data and attachments to Axis2BC provided endpoint. This endpoint provides access to an external web service.
- The Axis2BC takes all the data from the incoming JBI message and put it into the SOAP message
- The Axis2BC sends the SOAP message to the external web service
- Axis2BC is also configured to handle external on the address previously invoked. It consumes an endpoint provided by the File Transfer binding component (FTBC)
- Axis2BC handle the incoming SOAP message and put all the data (and attachments) into a new JBI message
- The JBI message is sent to the FTBC endpoint
- The FTBC endpoint receives the JBI message and write all the data to files
- 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
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
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:
- 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.
- Jetty is easily embeddable (Tomcat is not as easy as Jetty)
- 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:
- Create a new AxisService (org.apache.axis2.description.AxisService)
- Add parameters such as document definition for example (not used like this in the BC)
- 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 requestsParameter 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 serviceaxisConfig.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.AbstractDispatcherModify 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:
- MTOM : Message Transmission Optimization Mechanism
- 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:
- Use the client side options like this:
options.setProperty(Constants.Configuration.ENABLE_MTOM,Constants.VALUE_TRUE);
- Modify the server configuration file:
true
The SwA will be enabled like this:
- With the client side options:
options.setProperty(Constants.Configuration.ENABLE_SWA, Constants.VALUE_TRUE);
- Or by modifying the axis configuration file:
true
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
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
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 !
January 21, 2008 02:15 PM
January 17, 2008
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:
-
When the results came, the prices were in Swiss francs. Since I was in Switzerland but using a US credit card, I decided to switch my location using the quite nicely done language and location menu available on the result page.
I first noticed a funny glitch: for Switzerland, the language selection was English and German. English was selected by default, which suited me, but English was the second radio button in the list. When I switched to the United States location, the second radio button remained selected. However, since for that location the language selection was English first, then Spanish, the result was that the Spanish language was selected. Oops.
-
This was just a little bug though. The bigger problem was that as the language was switched, somehow the search page kept my flight dates, but lost the selected flights. So I had to go through them again.
-
When doing the final checkout, I omitted a digit in the credit card number. It took the web site almost one minute, after I pressed the submit button, to tell me that there was a problem with that number.
-
When that was fixed, I also happened to have forgotten to enter the billing address. The same thing happened: I had to wait for quite a long time after submitting the form to get a message telling me that that was wrong.
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:
-
With XForms, they easily set constraints, such as saying that the value of the radio button should be the currently selected value (say, ‘en’) if available, or then the default value if unavailable.
-
Localized user interface resources are stored in a separate XForms instance (which is an XML document). When switching the resources document, the entire user interface updates without losing the other data captured by the user.
-
XForms has several mechanisms to check input data: you can use XML Schema types or XPath constraints (XForms 1.1 even supports a credit card number type) to make sure that a Visa or Mastercard number is at least approximately correct in length and that the redundancy digit applies correctly.
-
XForms also support ways to mark fields as required so the user doesn’t forget to enter some information.
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
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
January 13, 2008
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
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
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
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
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
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
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
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
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
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:

Now I'll go on with some more usefull business logic.
December 17, 2007 12:26 PM
December 14, 2007
That's almost a note for my self:
GRANT ALL privileges ON . to 'username'@'localhost' identified by 'pwd' with gr