Expand my Community achievements bar.

Using createItem with Java AbstractAssembler

Avatar

Level 1
I've just started working with flex (and flex data services)
and have been experimenting with directly calling the createItem
method (extending AbstractAssembler) as a way of poking data into a
server-side DB. It's probable I'm just not using the flex
methodology correctly, but every time I try to run my test case I
am getting the error detailed below. I'd appreciate any pointers as
to where I'm going wrong...



Error in Tomcat log:


quote:



Exception in RtmpReader thread:
flex.messaging.MessageException: Cannot create class of type
'com.mycompany.learning.User'. Type 'com.mycompany.learning.User'
not found.

flex.messaging.MessageException: Cannot create class of type
'com.mycompany.learning.User'. Type 'com.mycompany.learning.User'

not found.

at
flex.messaging.util.ClassUtil.createClass(ClassUtil.java:57)

at
flex.messaging.io.AbstractProxy.createInstance(AbstractProxy.java:83)

at
flex.messaging.io.amf.Amf3Input.readScriptObject(Amf3Input.java:364)

at
flex.messaging.io.amf.Amf3Input.readObjectValue(Amf3Input.java:134)

at
flex.messaging.io.amf.Amf3Input.readObject(Amf3Input.java:116)

at
flex.messaging.io.amf.Amf3Input.readScriptObject(Amf3Input.java:392)

at
flex.messaging.io.amf.Amf3Input.readObjectValue(Amf3Input.java:134)

at
flex.messaging.io.amf.Amf3Input.readObject(Amf3Input.java:116)

at
flex.messaging.io.amf.Amf3Input.readArray(Amf3Input.java:323)

at
flex.messaging.io.amf.Amf3Input.readObjectValue(Amf3Input.java:138)

at
flex.messaging.io.amf.Amf3Input.readObject(Amf3Input.java:116)

at
flex.messaging.io.amf.Amf3Input.readScriptObject(Amf3Input.java:392)

at
flex.messaging.io.amf.Amf3Input.readObjectValue(Amf3Input.java:134)

at
flex.messaging.io.amf.Amf3Input.readObject(Amf3Input.java:116)

at
flex.messaging.io.amf.Amf0Input.readObjectValue(Amf0Input.java:125)

at
flex.messaging.io.amf.Amf0Input.readObject(Amf0Input.java:85)

at
flex.messaging.io.tcchunk.TCCommand.readMessage(TCCommand.java:177)

at
flex.messaging.endpoints.rtmp.AbstractRTMPServer.dispatchMessage(AbstractRTMPServer.java:563)

at
flex.messaging.endpoints.rtmp.NIORTMPConnection$RTMPReader.run(NIORTMPConnection.java:665)

at
edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:643)

at
edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:668)

at java.lang.Thread.run(Thread.java:613)







The client side Actionscript class looks like this:




quote:



package com.mycompany.learning

{

[RemoteClass(alias="com.mycompany.learning.User")]

public class User

{

public function User() {}



public var userId:int;



public var firstname:String;



public var surname:String;



public var email:String;



public var username:String;



public var password:String;



}

}







It's used in my mxml code as follows:




quote:





userDS = new DataService("account");

...

user = new User();

user.firstname = fNameV;

user.surname = sNameV;

user.username = userNameV;

user.password = passwordV;

user.email = userEmailV;

var ref:ItemReference = userDS.createItem(user);

Alert.show(ref.message.toString());







My destination xml definition looks like this:




quote:



<destination id="account">

<adapter ref="java-dao" />

<channels>

<channel ref="my-rtmp"/>

<channel ref="my-http"/>

</channels>

<properties>


<source>com.mycompany.learning.UserAssembler</source>

<scope>application</scope>

<metadata>

<identity property="userId"/>

</metadata>

<network>

<session-timeout>20</session-timeout>

<paging enabled="false" pageSize="10" />

<throttle-inbound policy="ERROR" max-frequency="500"/>

<throttle-outbound policy="REPLACE"
max-frequency="500"/>

</network>


<item-class>com.mycompany.learning.User</item-class>

</properties>

</destination>







And finally (sorry about the length of this posting) the java
code for the Assembler and server-side User object looks like this:




quote:





package com.mycompany.learning;



public class User

{

private int userId;

private String firstname;

private String surname;

private String email;

private String username;

private String password;



public String getFirstname()

{

return firstname;

}

...etc...

}








quote:





package com.mycompany.learning;



import java.util.*;



import flex.data.ChangeObject;

import flex.data.DataSyncException;

import flex.data.assemblers.AbstractAssembler;



public class UserAssembler extends AbstractAssembler

{



public List loadUsers()

{

UserDAO dao = new UserDAO();

return dao.getUsers();

}



public Object getItem(Map uid)

{

UserDAO dao = new UserDAO();

return dao.getUser(((Integer)
uid.get("userId")).intValue());

}



public void createItem(Object item)

{

System.out.println("HELLO!");

UserDAO dao = new UserDAO();

dao.create((User)item);

}

}







(I haven't seen the HELLO println call ever made.)
5 Replies

Avatar

Level 3
Hi Donald,



The error indicates that your com.mycompany.learning.User
class isn't available in the classpath of your web app so when your
Flex app ships a User instance down to the server, the server is
not able to locate/load the server side User class to deserialize
to. Make sure the class is available in
WEB-INF/classes/com/mycompany/learning/ or that it's in a jar file
in WEB-INF/lib



Best,

Seth

Avatar

Level 1
Hi -- thanks for the quick reply!



I agree that that seems to be the gist of the error message.
But the thing is, my classes
are in the "classes" folder of my app's WEB-INF, and they
are definitely in the server classpath -- I've tested this by
writing a simple servlet that imports and uses
com.mycompany.learning.User, without any problem... I'll try
packaging them as a jarfile (in "lib") to see if that makes a
difference.



Regards,

DI

Avatar

Level 2
My flex web apps are in a different directory than the flex
data service web app, so I've found it necessary to put my java
classes both in my web app and in the flex data service web app
(flex.war).



Mark

Avatar

Level 1
That solves it -- many thanks mark_in_fl (and seth_hodgson
for replying). Actually I can put my classes either in the
classpath of the flex webapp
or the classpath of the samples webapp and everything works
like a charm... which suggests either that these two paths are
hard-coded somewhere or (more likely) there is some config file
somewhere I've yet to find that alerts flex to your application's
directory name...



Anyway I'm happy that things are working. Best,



DI

Avatar

Level 1
Mark, according to your J2EE server, you could also change
your WAR classloader policy.



For instance on WebSphere (I use both 5.1 and 6.0 releases
here), I have a Module (default) and an Application scope. So,
either I drop all my JAR libraries (FDS and Java Flex application
classes) under the WEB-INF/lib directory, or I change the scope to
Application, without moving any JARs.



Partitioning is "more open" when you choose the Application
mode (which could be a problem under some circumstances, but that's
another topic).



Regards --