RoyZeng / flerry

Automatically exported from code.google.com/p/flerry
0 stars 0 forks source link

Null parameters results in fault. #5

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. Create java method that takes a parameter: 
public String helloWorld(String var){
   return "Hello World:"+var;
}
2. Call the method with 'null' value via NativeObject:
nativeObject.helloWorld(null);
3. Fault is returned instantaneously.
3: Pass a non "null" value to the Method: it returns as expected...

What is the expected output? What do you see instead?
Method should be called as expected, instead method is never reached... Fault 
occurs instantaneously after call.

What version of the product are you using? On what operating system?

Please provide any additional information below.
The fault returned has no details. Here is fault returned.

{"(mx.rpc.events.FaultEvent)" : 
 {
 "messageId(String)" : "D43A4727-C80D-106D-2FAB-90585D80074F"
 ,"fault(mx.rpc.Fault)" :  
 {
 ,"headers(object)" : null
 ,"cancelable(Boolean)" : "true"
 ,"type(String)" : "fault"
 ,"bubbles(Boolean)" : "false"
 ,"target(net.riaspace.flerry.NativeObject)" :  
}

I spent a long time figure out what was going on, but looks like 'null' is not 
getting serialized correctly and causing NativeObject process fault immediate 
after call.

Original issue reported on code.google.com by jay.jo...@hotmail.com on 28 Sep 2010 at 3:42

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
I found fix for this... issue is that null has no class.
so when getting paramTypes, params[i].class throws NullPointException. 
NullPointerException is not actually main issue though... 
Since you use paramTypes to call correct method, you need the class to get 
method definition to invoke...
So I added test if this fails, then loop through all methods via reflection and 
continue to attempt until return value is defined. 
Code I used to accomplish this... Great tool, hope this helps to improve. cheers

Object[] params = (Object[]) message.getBody();
                            Class<?>[] paramsTypes = new Class[params.length];
                            for (int i = 0; i < paramsTypes.length; i++) {  
                                if(params[i] == null) paramsTypes[i] = Object.class;
                                else paramsTypes[i] = params[i].getClass();
                            }
                            Object result = null;
                            boolean resultDefined = false;
                            NoSuchMethodException nsme = null;
                            String methodName = message.getOperation();
                            try{
                                result = sourceObject.getClass().getMethod(methodName, paramsTypes)
                                    .invoke(sourceObject, params);
                                resultDefined = true;
                            }catch(NoSuchMethodException e){
                                // error casting paramTypes, usually caused by 'null' object...
                                // try all methods matching name until get result... or fail
                                nsme = e;

                                Method[] methods = sourceObject.getClass().getDeclaredMethods();
                                 for (int i = 0; i < methods.length;  i++) {  
                                     Method method = methods[i];
                                     if(!methodName.equals(method.getName())) continue;

                                     try{
                                         result = method.invoke(sourceObject, params);
                                         resultDefined = true;
                                      }catch(IllegalAccessException e2){
                                         continue;
                                     }catch(IllegalArgumentException e2){
                                         continue;
                                     }catch(InvocationTargetException e2){
                                         resultDefined = true;
                                         throw e2;
                                     }
                                  }
                            }

                            if(!resultDefined && nsme != null) throw nsme;
                            sendMessage(result, message.getMessageId());

Original comment by jay.jo...@hotmail.com on 1 Nov 2010 at 9:04

GoogleCodeExporter commented 9 years ago
attaching my version of NativeObject.java so you have complete version for 
reference... cheers

Original comment by jay.jo...@hotmail.com on 1 Nov 2010 at 9:05

Attachments:

GoogleCodeExporter commented 9 years ago

Original comment by khronnuz@gmail.com on 25 Jul 2011 at 5:58

GoogleCodeExporter commented 9 years ago
Integrated suggestion. Thanks. This also fixes a issue with multiple methods 
with same name.

Original comment by khronnuz@gmail.com on 25 Jul 2011 at 6:36

GoogleCodeExporter commented 9 years ago
Thanks for your efforts and fixing this issue! I have one more suggestion 
though, which would further improve this piece of code...

In order to fully support method overloading (which can be quite handy in some 
situations ;-) ), we should not only compare the method name but look for a 
complete signature match of the operation in question. For example, this could 
be achieved by the following code snippet:

/////////////////////////////////////////////////////////////
Object[] messageParams = (Object[]) message.getBody();
Method[] methods = sourceObject.getClass().getMethods();
for (Method method : methods) {
  if (method.getName().equals(message.getOperation()) &&
    method.getParameterTypes().length == messageParams.length) {
      boolean signatureMatch = true;
      Class<?>[] methodParams = method.getParameterTypes();
      for(int p=0;p<methodParams.length;++p) {
        if(!methodParams[p].equals(messageParams[p].getClass())) {
          signatureMatch = false;
          break;
        }
      }
      if(signatureMatch) {
        try {
          Object result = method.invoke(sourceObject,messageParams);
          sendMessage(result, message.getMessageId());
        } catch(InvocationTargetException exc){
          exc.printStackTrace();
          handleException(exc.getCause(), message.getMessageId());
        }
      }
    }
  }
/////////////////////////////////////////////////////////////

Maybe you could take into account this suggestion for one of the upcoming 
versions.

Kind regards,

H.P. Grahsl

Original comment by grahs...@gmail.com on 25 Jul 2011 at 7:44