Home Tutorials Forums Articles Blogs Movies Library Employment Press

Go Back   ActionScript.org Forums > Supporting Technologies > Flash Remoting

Reply
 
Thread Tools Rate Thread Display Modes
Old 05-09-2005, 07:23 AM   #1
amerywu
Registered User
 
Join Date: Apr 2005
Posts: 26
Default Remoting with openAMF and java

I have a problem. But firstly for the archives, here are the bits that work. I hope it well help a few people get up and running a little faster than I did. Oopenamf is not exactly the world's best documented project.

My user bean in AS:

NOTE: The property names (not the getter names) in the AS class must match the getter and setter names in the java class.

ActionScript Code:
import mx.remoting.NetServices; class BMUser {     public var userName:String;     public var pword:String;     public var uid:Number;     public var lastLogin:Number;     function BMUser() {         trace(userName+" "+pword+" "+uid+" "+lastLogin);     }     function getUserName():String {         return userName;     }     function setUserName(in_s:String) {         userName = in_s;     }     function getPword():String {         return pword;     }     function setPword(in_s:String) {         pword = in_s;     }     function getUid():Number {         return uid;     }     function setUid(in_id:Number) {         uid = in_id;     }     function getLastLogin():Number {         return lastLogin;     }     function setLastLogin(in_l:Number) {         lastLogin = in_l;     } }

My communication class in AS:

ActionScript Code:
import mx.remoting.NetServices; class UserDirectory {         private var gatewayPath:String = "";     private var servicePath:String = "";     private var serviceConnection:Object = new Object();     private var serviceObject:Object = new Object();             public static var _instance:UserDirectory     public static function getInstance():UserDirectory     {         if(_instance == undefined)         {             _instance = new UserDirectory()         }         return _instance     }         private function UserDirectory() {         this.gatewayPath = GLOBALS.gatewayPath;         this.servicePath = "";         this.setServicePath("com.jakestone.bm.remoting.UserDirectory");         this.setServiceObject();     }     function getGatewayPath():String {         return gatewayPath;     }     function setGatewayPath(in_s:String) {         gatewayPath = in_s;     }     function getServicePath():String {         return servicePath;     }     function setServicePath(in_s:String) {         servicePath = in_s;     }     function setServiceObject() {         trace("UserDirectory settingserviceObject");         NetServices.setDefaultGatewayUrl(this.gatewayPath);         this.serviceConnection = NetServices.createGatewayConnection();         this.serviceObject = this.serviceConnection.getService(this.servicePath, this);     }         function login(user:BMUser) {         try {             trace("UserDirectory:login username="+user.getUserName());             trace("UserDirectory:login username="+user.getPword());             this.setServiceObject();             this.serviceObject.login(user);         } catch (errorObj:Error) {             trace(errorObj.message);         }     }     function login_Result(loginresult:BMUser) {         try {             trace("UserDirectory:login_result loginresult.getLastLogin()="+loginresult.getLastLogin());             if (undefined == loginresult.getLastLogin()) {                 trace(" Login Failed");             } else {                 trace(" Login Succeeded");             }         } catch (errorObj:Error) {             trace(errorObj.message);         }     } }

This works fine as is butdidn't work when I tried to create a superclass for some of the methods such as setServiceObject. This just needs reviewing. I'm sure it can be done.

SERVER SIDE:

openamf.config.xml
Code:
<?xml version="1.0" encoding="UTF-8"?>
<config>

	<!--
	Configure behavior of outgoing AMF messages:
	forceLowerCaseKeys - if true, the hash maps used to return custom classes
	will convert all keys to lower case; 
	set this to:
		true if you're using ActionScript 1.0 on the client,
		false if you're using ActionScript 2.0 (which is case-sensitive)
	-->
	<amf-serializer>
			<force-lower-case-keys>true</force-lower-case-keys>
	</amf-serializer>
       
	<!-- Required for DefaultGateway-->
	<invoker>
		<name>PageableRecordSet</name>
		<class>org.openamf.invoker.PageableResultSetServiceInvoker</class>
	</invoker>
	<invoker>
		<name>SessionControl</name>
		<class>org.openamf.invoker.SessionControlInvoker</class>
	</invoker>
	<invoker>
		<name>WebService</name>
		<class>org.openamf.invoker.WebServiceInvoker</class>
	</invoker>
	<invoker>
		<name>JMX</name>
		<class>org.openamf.invoker.JMXServiceInvoker</class>
	</invoker>
	
	<!-- Uncomment this to enable EJB invoker
	<invoker>
		<name>EJB</name>
		<class>org.openamf.invoker.EJBServiceInvoker</class>
	</invoker>
	-->
	
	<invoker>
		<name>Java</name>
		<class>org.openamf.invoker.JavaServiceInvoker</class>
	</invoker>
	<pageable-recordset>
		<initial-data-row-count>20</initial-data-row-count>
	</pageable-recordset>
	<!-- 
	Example Custom Class to Java Class mapping
	
	When a class of type org.openamf.examples.Person is Serialized
	it will be registered to Person in flash 
	
	When a custom class of Person is Deserialized it
	will be translated to an org.openamf.examples.Person
	
	<custom-class-mapping>
		<java-class>org.openamf.examples.Person</java-class>
		<custom-class>Person</custom-class>
	</custom-class-mapping>
	-->
	<!-- Required  for AdvancedGateway -->
	<!-- 
		This allows you to declare infomation about your services,
		instead of having the DefaultGateway guess 
	-->
	<service>
		<name>SessionControlService</name>
		<invoker-ref>SessionControl</invoker-ref>
		<method>
			<name>close</name>
			<parameter>
				<type>*</type>
			</parameter>
		</method>
	</service>
	<service>
		<name>OpenAMFPageableRecordSet</name>
		<invoker-ref>PageableRecordSet</invoker-ref>
		<method>
			<name>*</name>
			<parameter>
				<type>*</type>
			</parameter>
		</method>
	</service>
	<service>
		<name>Test</name>
		<service-location>com.jakestone.bm.Test</service-location>
		<invoker-ref>Java</invoker-ref>
		<method>
			<!-- Operation's are matched by the name and parameters -->
			<name>sayHello</name>
			<state-bean-ref>
				<name>Authentication</name>
			</state-bean-ref>
			<parameter>
				<!-- 
					type can be the the name of the class, 
					a * for any types,
					or a ? any 1 type
				-->
				<type>*</type>
			</parameter>
		</method>

	</service>
    <service>
		<name>UserDirectory</name>
		<service-location>com.jakestone.bm.remoting.UserDirectory</service-location>
		<invoker-ref>Java</invoker-ref>
		<method>
			<!-- Operation's are matched by the name and parameters -->
			<name>login</name>
			<state-bean-ref>
				<name>Authentication</name>
			</state-bean-ref>
			<parameter>
				<!--
					type can be the the name of the class,
					a * for any types,
					or a ? any 1 type
				-->
				<type>com.jakestone.bm.datamodel.BMUser</type>
			</parameter>
		</method>

	</service>
	<state-bean>
		<name>Authentication</name>
		<class>org.openamf.examples.Authentication</class>
		<scope>session</scope>
	</state-bean>
</config>
My web.xml. (Password to db is TOP SECRET so don't read it)

Code:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
  Copyright 2004 The Apache Software Foundation

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->

<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>

    <display-name>Brain Map Project</display-name>
    <description>
        Brain Map Project.
    </description>


    <servlet>
        <servlet-name>InitServlet</servlet-name>
        <servlet-class>com.jakestone.bm.servlet.InitServlet</servlet-class>

        <init-param id="param1">
            <param-name>
                DRIVER
            </param-name>
            <param-value>
                com.mckoi.JDBCDriver
            </param-value>
        </init-param>
        <init-param id="param2">
            <param-name>
                USER
            </param-name>
            <param-value>
                bmdb
            </param-value>
        </init-param>
        <init-param id="param3">
            <param-name>
                PASSWORD
            </param-name>
            <param-value>
                bmdb
            </param-value>
        </init-param>
        <init-param id="param4">
            <param-name>
                URL
            </param-name>
            <param-value>
                jdbc:mckoi:local://../webapps/bm/mckoi/db.conf
            </param-value>
        </init-param>
        <init-param id="param5">
            <param-name>
                logLevel
            </param-name>
            <param-value>
                FINEST
            </param-value>
        </init-param>
        <init-param id="param6">
            <param-name>
                logFile
            </param-name>
            <param-value>
                ../webapps/bm/logs/bmwebapp.log
            </param-value>
        </init-param>
        <init-param id="param7">
            <param-name>
                mckoiDir
            </param-name>
            <param-value>
                ../webapps/bm/mckoi
            </param-value>
        </init-param>
        <load-on-startup>2</load-on-startup>
    </servlet>


    <servlet>
        <servlet-name>DefaultGateway</servlet-name>
        <display-name>DefaultGateway</display-name>
        <description>DefaultGateway</description>
        <servlet-class>org.openamf.DefaultGateway</servlet-class>
        <init-param>
            <param-name>OPENAMF_CONFIG</param-name>
            <param-value>/WEB-INF/openamf-config.xml</param-value>
            <description>Location of the OpenAMF config file.</description>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>DefaultGateway</servlet-name>
        <url-pattern>/gateway</url-pattern>
    </servlet-mapping>




    <servlet-mapping>
        <servlet-name>InitServlet</servlet-name>
        <url-pattern>/InitServlet</url-pattern>
    </servlet-mapping>


</web-app>
My service class:
Code:
package com.jakestone.bm.remoting;

import com.jakestone.bm.datamodel.BMUser;
import com.jakestone.bm.utils.BMLogManager;

import java.util.logging.Level;
import java.io.Serializable;

/**
 * Created by IntelliJ IDEA.
 * User: Jacob
 * Date: May 8, 2005
 * Time: 8:59:05 PM
 * To change this template use Options | File Templates.
 */
public class UserDirectory implements Serializable
{
    public BMUser login(BMUser user)
    {
        try
        {

            BMLogManager.getDefaultLogger().log(Level.INFO,"user is "+user.toString());
            user.login();
            return user;
        }
        catch(Exception e)
        {
            BMLogManager.getDefaultLogger().log(Level.WARNING,"EXCEPTION IN DIRECTORY"+e.toString(),e);
        }
        return null;
    }
}

and my userbean which talks to a DAO:


Code:
package com.jakestone.bm.datamodel;

import com.jakestone.bm.BMException;
import com.jakestone.bm.ExceptionEncoder;
//import com.jakestone.bm.servlet.Constants;
//import com.jakestone.bm.servlet.XMLWrap;
import com.jakestone.bm.utils.BMLogManager;

import java.sql.Date;
import java.util.logging.Level;
import java.io.Serializable;


/**
 * Created by IntelliJ IDEA.
 * User: jake
 * Date: Jun 26, 2004
 * Time: 8:09:42 AM
 * To change this template use Options | File Templates.
 */
public class BMUser extends BMAbstractDataObject implements Serializable
{

    private String userName;
    private String pword;
    private long lastLogin;


    public long getUid()
    {
        return uid;
    }

    public void setUid(long in_id)
    {
        uid = in_id;
    }

    public BMException getBMException()
    {
        return exception;
    }

    public void setBMException(BMException in_exception)
    {
        exception = in_exception;
    }

    public String getUserName()
    {
        return userName;
    }

    public String getPword()
    {
        return pword;
    }

    public long getLastLogin()
    {
        return lastLogin;
    }


    public void setUserName(String in_userName)
    {
        userName = in_userName;
    }

    public void setPword(String in_password)
    {
        pword = in_password;
    }

    public void setLastLogin(long in_lastLogin)
    {
        lastLogin = in_lastLogin;

    }

    public Date showLastLogin()
    {
        return new Date(lastLogin);
    }


    protected void doInsert() throws BMDataModelException
    {
        //BMLogManager.getDefaultLogger().log(Level.FINE, "inserting ");
        BMUserMgr.getInstance().doInsert(this);
    }

    protected void doUpdate() throws BMDataModelException
    {
        BMUserMgr.getInstance().doUpdate(this);
    }

    public void doPopulate() throws BMDataModelException
    {
        BMUserMgr.getInstance().populate(this);
    }

    public void doDelete() throws BMDataModelException
    {
        BMUserMgr.getInstance().delete(this);
    }

    public void populate(String un, String pw) throws BMDataModelException
    {
        this.userName = un;
        this.pword = pw;
        BMUserMgr.getInstance().populate(this);
    }

    protected void validate() throws BMException
    {
        if (null == pword || null == userName)
        {
            BMLogManager.getDefaultLogger().log(Level.WARNING, "Username or pword is blank");

            BMException exc = new BMException("Username or pword is blank");
            exc.setHumanMessage("Username or pword is blank");

            throw  exc;
        }

        if (userName.length() > 16)
        {
            BMLogManager.getDefaultLogger().log(Level.WARNING, "User name longer than 16 characters");
            BMException exc = new BMException("User name longer than 16 characters");
            exc.setHumanMessage("User name longer than 16 characters");

            throw  exc;
        }
        else if (userName.length() > 16)
        {
            BMLogManager.getDefaultLogger().log(Level.WARNING, "Password longer than 16 characters");
            BMException exc = new BMException("Password longer than 16 characters");
            exc.setHumanMessage("Password longer than 16 characters");

            throw  exc;
        }
    }

    public void login()
    {
        try
        {

                try
                {
                    BMLogManager.getDefaultLogger().log(Level.FINE, "db is local");

                    BMUserMgr.getInstance().login(this);


                }
                catch (Exception e)
                {
                    BMLogManager.getDefaultLogger().log(Level.FINE, e.getMessage());
                    setBMException(ExceptionEncoder.encodeException(e));
                }


        }
        catch (Exception e)
        {

            this.setBMException(ExceptionEncoder.encodeException(e));


            BMLogManager.getDefaultLogger().log(Level.FINE, "standard exception" + e.getMessage());
        }

    }

    public String toString()
    {
        return super.toString() + "\r\nuser=" + userName + "\r\nlastlogin=" + lastLogin;
    }

}

All of this works up to the point where the BMUser instance is received back at the client in the login_Result method of UserDirectory

Last edited by amerywu; 05-09-2005 at 05:46 PM.
amerywu is offline   Reply With Quote
Old 05-09-2005, 07:27 AM   #2
amerywu
Registered User
 
Join Date: Apr 2005
Posts: 26
Default And now my problem .....

I know that a corectly instantiated BMUser instance is dispatched by the server, but when it is received in the login_Result method of UserDirectory all properties are undefined. Furthermore, I put a trace method in the constructor of BMUser in AS, assuming it would be called before login_Result. It wasn't, which suggests that the client (ie Flash) did not even try to instantiate BMUser.


Any ideas ? I would be most grateful for some help


Jake
amerywu is offline   Reply With Quote
Old 05-09-2005, 04:42 PM   #3
amerywu
Registered User
 
Join Date: Apr 2005
Posts: 26
Default And now it all works

The answer is that whatever is returned from the server must be a standard java type such as String or ArrayList. You need to put your custom classes into the ArrayList.

I tried the custom class mappings in the openamf-config, but that didn't help.

so for the record.

All the above code works except the following modifications which need to be made.

SERVER SIDE:
Code:
public class UserDirectory implements Serializable
{
    public List login(BMUser user)
    {
        try
        {
            ArrayList l = new ArrayList();
            BMLogManager.getDefaultLogger().log(Level.INFO,"user is "+user.toString());
            user.login();
            l.add(user);
            return l;
        }
        catch(Exception e)
        {
            BMLogManager.getDefaultLogger().log(Level.WARNING,"EXCEPTION IN DIRECTORY"+e.toString(),e);
        }
        return null;
    }
}

CLIENT SIDE UserDirectory class

ActionScript Code:
function login_Result(loginresult) {         try {                          this.list = loginresult;     _root.responseOut.text = "RESULT COUNT: "+loginresult.length+"\n\n";     for (var i=0; i<loginresult.length;i++)     {            var n = loginresult[i]         var un = n["userName"].toString();         var lastlogin = n["lastLogin"].toString();         trace (un+"  "+lastlogin);     }         } catch (errorObj:Error) {             trace(errorObj.message);         }     } }


I hope this proves to be useful reference for any others that wish to use openamf. It seems to be an awesome tool, just needed slightly better documentation

Jake
amerywu is offline   Reply With Quote
Reply


Thread Tools
Display Modes Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Forum Jump


All times are GMT. The time now is 07:43 AM.

///
Follow actionscriptorg on Twitter

 


Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Ad Management plugin by RedTyger
Copyright 2000-2013 ActionScript.org. All Rights Reserved.
Your use of this site is subject to our Privacy Policy and Terms of Use.