5 Replies Latest reply on May 20, 2007 8:11 PM by el Fakir

    Using createItem with Java AbstractAssembler

    donald_i
      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(ThreadPo olExecutor.java:643)
      at edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolEx ecutor.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.)
        • 1. Re: Using createItem with Java AbstractAssembler
          seth_hodgson Level 1
          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
          • 2. Re: Using createItem with Java AbstractAssembler
            donald_i 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
            • 3. Re: Using createItem with Java AbstractAssembler
              mark_in_fl
              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
              • 4. Re: Using createItem with Java AbstractAssembler
                donald_i 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
                • 5. Re: Using createItem with Java AbstractAssembler
                  el Fakir
                  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 --