Archive for the ‘Uncategorized’ Category

SQLLoader and ORA-04043

I had to import almost half of billion rows in one Oracle table and for that I wrote a small SQLLoader script (below):

"load data infile * append into table "usermonth....."

And I received the following error message

"SQL*Loader-941: Error during describe of table "usermonth"
ORA-04043: object "usermonth" does not exist"

After one hour of despair and I realized by pure luck that you need to provide the name of the table with upper case, otherwise the utility is not able to find it. Quite strange, but at least I’m happy that now it works.

Java exceptions and Flex

I’ve seen some articles on this subject but I have not found one dealing with all cases (webservices, BlazeDS, BlazeDS and Spring, data management). Also the approach for BlazeDS is different than the one used with Spring/BlazeDS integration, and this thing can be a little bit confusing for a beginner.

Let’s assume that you have a layer of services that should be invoked from your Flex application. You can expose these services as web services or as remote methods. Or you can use data management. The Java methods may throw errors and you want to display them in the Flex application.

For simplicity I will use a very short method as an example. The method signature is :

public String returnResults() throws DatabaseDownException;

There are four main use cases:

a)You have to write a webservice to return the result as XML. For example:

<?xml version="1.0" encoding="UTF-8"?>
<data>
<result>
</result>
</data>

In this case you will need to enhance your XML to add a structure for keeping error messages – like this:

<?xml version="1.0" encoding="UTF-8"?>
<data>
<result>
</result>
<error>
</error>
</data>

When building the XML the <error> body is going to envelope the exception message. Of course more information can be added, including exception type, severity, and so on. The same approach should be used also when working with SOAP services

b)You plan to use BlazeDS and Java remoting

In this case things are going to be easier,  because BlazeDS is able to automatically serialize the thrown exception and you can find the serialized exception in the FaultEvent object. Assume that you have the Java exception declared below. It extends the RuntimeException and it has a getter method for a custom field.

public class DatabaseDownException extends RuntimeException{
private String customField;
public String getCustomField(){
return customField;
}
}

The Flex code declares a remote object and registers a handler (which is also included) for failure.

<mx:RemoteObject id="test" destination="testDestination" result="resultHandler(event)" fault="faultHandler(event)"/>
private function faultHandler(event:FaultEvent):void{
var exception:Object = event.fault.rootCause;
Alert.show(exception.cause);
Alert.show(exception.localizedMessage);
Alert.show(exception.message);
Alert.show(exception.customField);
}

There are four fields in the serialized exception. The first three are inherited from the Throwable object, the last one is declared in your exception. It is interesting to note that you need not have a pair of set/get function in order to have your property serialized. The Throwable object is the only object in which  it is enough to have get methods in order to serialize the values (you can take a look at flex.messaging.io.ThrowableProxy to check that).

The only drawback is that you are working with untyped objects..if you don’t like that you can throw instead instances of flex.messaging.MessageException. This Java class is part of the BlazeDS and it will be deserialized using the class mx.messaging.messages.ErrorMessage (obtained from the event.message property).

You can add your custom data in the MessageException class using the extended property. For example:

MessageException messageException = new MessageException();
HashMap<String,String> map = new HashMap<String,String>();
map.put("clientName", "JOHN");
map.put("clientSurname", "MASTER");
messageException.setExtendedData(map);
messageException.setCode("ACCOUNT_DISABLED");
throw messageException;

And on the Flex side:

private function faultHandler(event:FaultEvent):void{
var errorMessage:ErrorMessage = event.message as ErrorMessage;
trace(errorMessage.extendedData.clientName);
trace(errorMessage.extendedData.clientSurname);
trace(errorMessage.faultCode);
}

You probably do not want to have an explicit dependence between your service layer and the BlazeDS libraries, so in this case you should build a delegate on top of it, which will also act as an exception translator.

c)Using Spring BlazeDS Integration

You have several benefits when using Spring BlazeDS integration, and if your middle tier is already using Spring it’s a must. The benefit related to exception handling is the exception translator mechanism. This translator will catch all the exceptions thrown from the services invoked from Flex and you can translate them into something more meaningful for the client.

First you need to declare the exception translator:

<bean id="exceptionTranslator" class="com.test.exception.ExceptionTranslatorImpl" />
<flex:message-broker services-config-path="/WEB-INF/flex/services-config.xml">
........
<flex:exception-translator ref="exceptionTranslator" />
</flex:message-broker>

The exception translator is below:

public class ExceptionTranslatorImpl implements ExceptionTranslator{
//handles all
public boolean handles(final Class<?> clazz){
return true;
}
public MessageException translate(final Throwable throwable){
if (throwable instanceof DatabaseDownException){
MessageException exception = new MessageException();
exception.setCode("FATAL_DB_DOWN");
return exception;
}
if ...........//check another things
}
}

Note that in the current version of Spring/BlazeDS integration it is mandatory to have an exception translator, otherwise the original error is going to be swallowed and you will receive some generic error.

d)Using data management

The same approach from point c) applies here. Basically your assembler – which is going to invoke some service to obtain/create data – will take care of translating the exceptions into something meaningful for the client. I wrote some time ago a short post about that here.

Note: this article was translated also in Belorussian (thanks Patricia), you can find it here.

Understanding the Market for Software Platforms

Jeff Vroom, the former BlazeDS & LiveCycle architect wrote an interesting article – Understanding the Market for Software Platforms. As a former TopLink user I can make a parallel between his examples and the comparison between Hibernate/TopLink. The former one was on the market for several years before of Hibernate and it was a very powerful ORM framework, however it lost the battle because the company acquiring it had no offer for the horizontal market – that means only a very low number of developers were using it, no books, very few articles and learning materials, and slower evolution in comparison with the Hibernate framework.

Survey – Flash Builder roadmap

Andrew Shorten, the new Flash Builder product manager, created a survey where you can express what do you want for the future version of the product. It takes 15 minutes and you can win some gadget if you are from USA or Canada. I think that if you are using Flash Builder you should fill in the survey – it is taken seriously, and there a lot of things to improve in this product.

The link for the survey is here.

LCDS, ManagedObjectProxy and some reserved keywords

Yesterday I struggled for several hours looking in the Livecycle Data Services code in order to investigate the following error message:TypeError: Error #1034: Type Coercion failed: cannot convert “ZGUID” to QName. It was not easy but in the end I understood that it is an issue related to property collision inside of the ManagedObjectProxy  class. The ManagedObjectProxy instance is adding all the properties from the serialized objects into it. However if the name of one of your properties already exists in the ManagedObjectProxy instance then this process will fail. The following properties already exist (inherited from ObjectProxy):

dispatcher : EventDispatcher
notifiers : Object
object : Object
propertyList : Array
proxyClass : Class
type : QName
uid:String

For the “type” property a fix was provided in Livecycle Data Services 3, but not for the others. So if you design your domain object and you plan to use Livecycle Data Services it’s a good idea to not use this reserved keywords as names for your properties.

The problem appears only if you like to use the proxy approach (not having the corresponding AS class included in the client SWF).

Netflix Values Presentation

A colleague of mine sent me this link from TechCrunch related to an internal Netflix presentation. It’s really interesting and I highly recommand to spend some time reading the slides (and to pass it to your manager). I’m not sure if this works for a larger company but at the first glance it looks like the perfect job – if you like both responsibility and autonomy.

Flex Camp – Cluj Napoca

Transylvania Flex Group is organizing a Flex Camp in Cluj Napoca on 15 October. You can see the full agenda and register here.

MAX Companion AIR Application

You can go this URL and install a nice AIR application – it offers three main functionalities: Twitter (all the messaged having #adobemax), session tracking and maybe the most important one- a map to quickly find the conference rooms and other locations.

Adobe Max online

As most of you know there is no Adobe Max in Europe this year. For the ones not able to go to Los Angeles you can register on Adobe Max online – the keynotes are going to be streamed live. You can also view the top session of the day from each track: Design, Develop, and Envision.

Logging everything in BlazeDS

When you create a Flex/Java project in Flex Builder the logging tag in the services-config.xml file looks like that:

    <logging>
        <target class="flex.messaging.log.ConsoleTarget" level="Error">
            <properties>
                <prefix>[BlazeDS] </prefix>
                <includeDate>false</includeDate>
                <includeTime>false</includeTime>
                <includeLevel>false</includeLevel>
                <includeCategory>false</includeCategory>
            </properties>
            <filters>
                <pattern>Endpoint.*</pattern>
                <pattern>Service.*</pattern>
                <pattern>Configuration</pattern>
            </filters>
        </target>
    </logging>

Unfortunately you can lose some important error messages with this <filters> configuration. That’s why its better to edit the file after creating the project and change the filters section to *

    <filters>
        <pattern>*</pattern>
    </filters>