Dashboard > Documentation > ... > 2.4. Configurable Options > 2.4.4. Miscanellous

View Info

2.4.4. Miscanellous

 Documentation Summary
 Page Summary

Custom Converter

If you need special type conversion support (like Joda time to regular AS3 Date), you may use a custom converter and reference it in your granite-config.xml like that:

granite-config.xml
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE granite-config PUBLIC
    "-//Granite Data Services//DTD granite-config internal//EN"
    "http://www.graniteds.org/public/dtd/1.0.0/granite-config.dtd">

<granite-config>
  <converter type="path.to.MyCustomConverter"/>
</granite-config>

Your custom converter must implement the org.granite.messaging.amf.io.util.Converter interface (it could of course extend the org.granite.messaging.amf.io.util.DefaultConverter class) and 3 methods:

public Object convertForSerialization(Object value);

public Object convertForDeserialization(Object value, Type targetType);

public ServiceInvocationContext findServiceMethod(
    Map<String, Object> headers,
    Destination destination,
    Object service,
    String methodName,
    Object[] params) throws NoSuchMethodException;

See Javadoc comments in org.granite.messaging.amf.io.util.Converter and default implementation for further details.

See also the Gas3 java2as3class option here in order to extend code generation for your custom types.

Custom Exception Handler

If you need special service exception handling (either to add extra informations or to mask implementation details), you may configure a custom ServiceExceptionHandler in services-config.xml:

services-config.xml
<?xml version="1.0" encoding="UTF-8"?>

<services-config>
  ...
  <factories>
    <factory id="..." class="...">
      <properties>
        <service-exception-handler>
          path.to.my.CustomServiceExceptionHandler
        </service-exception-handler>
        ...
      </properties>
    </factory>
  </factories>
  ...
</services-config>

Your custom service exception handler must implement the org.granite.messaging.service.ServiceExceptionHandler interface (it could of course extend the org.granite.messaging.service.DefaultServiceExceptionHandler class) and 2 methods:

public ServiceException handleNoSuchMethodException(
    Message request,
    Destination destination,
    Object invokee,
    String method,
    Object[] args,
    NoSuchMethodException e
);

public ServiceException handleInvocationException(
    ServiceInvocationContext context,
    Throwable t
);

The first method is called whenever the service invoker cannot find any suitable method with the supplied name and arguments.

The second one is called whenever the method invocation throws an exception. Note that java.lang.reflect.InvocationTargetException are unwrapped (getTargetException) before handleInvocationException is called.

In both cases, the returned ServiceException will be trown (and serialized in a Flex ErrorMessage) instead of the raw NoSuchMethodException e or Throwable t one.

Custom Class Getter

A problem with the default AMF3 serialization is to get the true class name of an object in special cases. For example, a simple myObject.getClass().getName() with a proxied entity bean would return "org.hibernate.proxy.HibernateProxy" instead of the underlying entity bean class name. In order to get through this kind of problem, you must configure a class getter.

For example, here is the full configuration used in graniteds-ejb3-1.0.0.zip:

granite-config.xml
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE granite-config PUBLIC
    "-//Granite Data Services//DTD granite-config internal//EN"
    "http://www.graniteds.org/public/dtd/1.0.0/granite-config.dtd">

<granite-config>
  <classgetter type="org.granite.hibernate.HibernateClassGetter"/>

  <externalizers>
    <externalizer type="org.granite.hibernate.HibernateExternalizer">
      <include instanceof="test.granite.ejb3.entity.AbstractEntity"/>
    </externalizer>
  </externalizers>
</granite-config>

The org.granite.hibernate.HibernateClassGetter class is used in order to retreive the correct entity class name from a proxy. You may write and plug your own class getter in a similar way.

Custom Java or ActionScript3 Class Descriptors

When a Java object is not Externalizable nor externalized by a GDS externalizer, it is serialized by the mean of the org.granite.messaging.amf.io.util.DefaultJavaClassDescriptor. This class controls which fields must be serialized and how to retrieve values from those fields.

In similar situations, but at deserialization time, the org.granite.messaging.amf.io.util.DefaultActionScriptClassDescriptor class controls how the corresponding Java object is instanciated and how values are set in this new instance.

You may write and plug your own Java or ActionScript3 descriptors, for example:

MyJavaClassDescriptor.java
public class MyJavaClassDescriptor
    extends org.granite.messaging.amf.io.util.JavaClassDescriptor {

    public MyJavaClassDescriptor(Class type) {
        super(type);
    }

    @Override
    protected List<Property> introspectProperties() {
        // put your custom code here...
    }
}
MyAS3ClassDescriptor.java
public class MyAS3ClassDescriptor
    extends org.granite.messaging.amf.io.util.ActionScriptClassDescriptor {

    public MyAS3ClassDescriptor(String type, byte encoding) {
        super(type, encoding);
    }

    @Override
    public void defineProperty(String name) {
        // put your custom code here...
    }

    @Override
    public Object newJavaInstance() {
        // put your custom code here...
    }
}

Then, you should put this kind of declaration in your granite-config.xml:

granite-config.xml
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE granite-config PUBLIC
    "-//Granite Data Services//DTD granite-config internal//EN"
    "http://www.graniteds.org/public/dtd/1.0.0/granite-config.dtd">

<granite-config>
    <descriptors>
        <descriptor
            type="path.to.MyClass"
            java="path.to.MyJavaClassDescriptor"
            as3="path.to.MyAS3ClassDescriptor" />
        <descriptor
            instanceof="path.to.MyBaseClass"
            java="path.to.MyJavaClassDescriptor"
            as3="path.to.MyAS3ClassDescriptor" />
        <!-- other descriptor configuration... -->
    </descriptors>
</granite-config>

You must use only one of type or instanceof attributes (ie: should my descriptor(s) be used for all path.to.MyClass objects or for all instances of path.to.MyBaseClass); you may use one of (or both) java or as3 attributes.

Custom AMF3 (De)Serializers

You may plug your own AMF3 serializer/deserializer.

A custom AMF3 serializer must implement java.io.ObjectOutput and have a special constructor signature:

MyAMF3Serializer.java
public class MyAMF3Serializer implements java.io.ObjectOutput {

    public MyAMF3Serializer(java.io.OutputStream out) {
        // ...
    }

    // ObjectOutput implemention...
}

Then, you must register this serializer in granite-config.xml:

granite-config.xml
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE granite-config PUBLIC
    "-//Granite Data Services//DTD granite-config internal//EN"
    "http://www.graniteds.org/public/dtd/1.0.0/granite-config.dtd">

<granite-config>
    <amf3serializer type="path.to.MyAMF3Serializer"/>
</granite-config>

A custom AMF3 deserializer must implement java.io.ObjectInput and have a special constructor signature:

MyAMF3Deserializer.java
public class MyAMF3Deserializer implements java.io.ObjectInput {

    public MyAMF3Deserializer(java.io.InputStream in) {
        // ...
    }

    // ObjectInput implemention...
}

Then, you must register this deserializer in granite-config.xml:

granite-config.xml
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE granite-config PUBLIC
    "-//Granite Data Services//DTD granite-config internal//EN"
    "http://www.graniteds.org/public/dtd/1.0.0/granite-config.dtd">

<granite-config>
    <amf3deserializer type="path.to.MyAMF3Deserializer"/>
</granite-config>

You may of course extend org.granite.messaging.amf.io.AMF3Serializer or org.granite.messaging.amf.io.AMF3Deserializer to override only some parts of the default AMF3 (de)serialization process (all methods in thoses classes are public or protected).

ServiceInvocationListener (advanced use only)

If you need to listen to each service invocation method call, you may plugin a org.granite.messaging.service.ServiceInvocationListener implementation like this:

granite-config.xml
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE granite-config PUBLIC
    "-//Granite Data Services//DTD granite-config internal//EN"
    "http://www.graniteds.org/public/dtd/1.0.0/granite-config.dtd">

<granite-config>
    <invocationlistener type="path.to.MyServiceInvocationListener"/>
</granite-config>

Your class must implement the org.granite.messaging.service.ServiceInvocationListener interface and 3 methods:

public Object[] beforeMethodSearch(Object invokee, String methodName, Object[] args);
public void beforeInvocation(ServiceInvocationContext context);
public Object afterInvocation(ServiceInvocationContext context, Object result);
Be very carefull with those listeners: you may broke the invocation process if you don't return proper args (beforeMethodSearch), if you modify the ServiceInvocationContext (beforeInvocation) or if you return a different object than the service method call result (afterInvocation)!

Browse Space
- Pages
- Labels
- Attachments
- Mail
- Bookmarks
- News
- Activity
- Advanced

Explore Confluence
- Popular Labels
- Notation Guide

Your Account
Log In

Other Features

View a printable version of the current page.

Add Content
- Add Comment


Powered by Atlassian Confluence, the Enterprise Wiki. (Version: 2.6.0 Build:#913 Sep 27, 2007)
Bug/feature request - Contact Administrators

SourceForge.net Logo
Copyright © 2007-2008 Adequate Systems. All Rights Reserved.