Running ok under host mode, Error on Tomcat

Hi,

im still trying to get familiar with SmartGwt. I made a simple login page, and DMI on the background to handle user authentication and session. It runs under hosted mode, everything is fine just a bit slow, so i wrapped up the project in a WAR file, and wanted to see how it performs on Tomcat. But when i click on a button to call a DMI method ‘tryLogin’, it returns an error:

org.apache.commons.collections.map.LinkedMap cannot be cast to java.lang.String

From the server logs, i saw this:

=== 2010-10-07 11:06:25,932 [88-4] DEBUG RPCManager - Request #1 (DSRequest) payload: {
    criteria:{
        username:{
            "0":"g",
            "1":"e",
            "2":"o",
            "3":"r",
            "4":"g",
            "5":"e",
            tI:2
        },
        password:{
            "0":"a",
            "1":"d",
            "2":"m",
            "3":"i",
            "4":"n",
            tI:2
        }
    },
    operationConfig:{
        dataSource:"userDmi",
        operationType:"fetch"
    },
    appID:"builtinApplication",
    operation:"tryLogin",
    oldValues:{
        username:{
            "0":"g",
            "1":"e",
            "2":"o",
            "3":"r",
            "4":"g",
            "5":"e",
            tI:2
        },
        password:{
            "0":"a",
            "1":"d",
            "2":"m",
            "3":"i",
            "4":"n",
            tI:2
        }
    }
}

this is quite different from what i saw when running under hosted mode:

     [java] === 2010-10-07 08:14:23,504 [l0-5] DEBUG RPCManager - Request #1 (DSRequest) payload: {
     [java]     criteria:{
     [java]         username:"george",
     [java]         password:"admin"
     [java]     },
     [java]     operationConfig:{
     [java]         dataSource:"userDmi",
     [java]         operationType:"fetch"
     [java]     },
     [java]     appID:"builtinApplication",
     [java]     operation:"tryLogin",
     [java]     oldValues:{
     [java]         username:"george",
     [java]         password:"admin"
     [java]     }
     [java] }

the parameters in Tomcat are converted to byte arrays some how, but they are Strings in hosted mode. Here’s how i set the criteria on the client side:

DSRequest request = new DSRequest();
		request.setOperationId("tryLogin");
		Criteria cri = new Criteria();
		String username = textItemUsername.getValue().toString();
		String password = passwordItemPassword.getValue().toString();
		cri.addCriteria("username", username);
		cri.addCriteria("password", password);
		
		SC.showPrompt("Please wait...");
		Datasource datasource = DataSource.get("userDmi");

		datasource.fetchData(cri, new DSCallback() {
			
			public void execute(DSResponse response, Object rawData, DSRequest request) {
				if(response.getStatus() == DSResponse.STATUS_FAILURE) {
					SC.clearPrompt();
				} else {
					GuiUtil.reload();
				}
			}
		}, request);

the userDmi.ds.xml

...
        <binding operationType="fetch" operationId="tryLogin" serverMethod="tryLogin">
            <serverObject className="au.com.sample.server.TransUserDMI" lookupStyle="new"/>
        </binding>
...

TransUserDMI.java

...

	
	public DSResponse tryLogin(DSRequest request, HttpServletRequest req) throws Exception {
		_log.info("Calling tryLogin");
		
		Map<String, String> cri = request.getCriteria();
//		String username = cri.get("username");   <=====
//		String password = cri.get("password");     <=====
		
		_log.info("---- " + request.getFieldValue("username") + ", " + request.getFieldValue("password"));
/*** the above line prints out: 07 Oct 11:06:25 INFO  nsact.server.TransUserDMI..tryLogin  :63  - ---- {0=g, 1=e, 2=o, 3=r, 4=g, 5=e, tI=2}, {0=a, 1=d, 2=m, 3=i, 4=n, tI=2} **/
		
		String username = (String)request.getFieldValue("username");  <====
		String password = (String)request.getFieldValue("password");  <====
		
		if(username.equals("george") && password.equals("admin")) {
			System.out.println("Username = " + username + ", Password = " + password);
			req.getSession().setAttribute("loginUser", "george");
		} else {
			DSResponse res = new DSResponse("Login failed!", DSResponse.STATUS_FAILURE);
			
			return res;
		}
		
		return request.execute();
	}
...

the error was reported on the lines that i marked arrows.

Server Error message:

=== 2010-10-07 11:06:25,934 [88-4] DEBUG DataSourceDMI - Invocation threw exception
java.lang.ClassCastException: org.apache.commons.collections.map.LinkedMap cannot be cast to java.lang.String
	at au.com.sample.server.TransUserDMI.tryLogin(TransUserDMI.java:65)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	......

Guys, please help, thank you!!!

This is a core GWT bug. Remove your explicit (and unnecessary) calls to toString() to avoid it.

To clarify, the Object returned from getValue() is already a String (or null), you just need to cast to (String) instead of calling toString(). This avoids a GWT compiler bug.

Thanks Iso, that’s excellent, working really well, now i can deploy my project to tomcat, thanks for your help!

I’ve added convenience getValueAs<Type> convenience methods to various FormItems so it should be easier to get their values without type conversion. For TextItem’s you can now call TextItem.getValueAsString().

Sanjiv