Listening to a bean to launch a method

Hi everybody,

I’ve developed a bean which allows the user to Drag and Drop files in it.
For the moment the user has to press a button to send the files dropped to the server.
But I would like start the upload as soon as the files are dropped. For that I have to listen to what going on the bean.

I found here that there is a method called setMethodToCallOnClick which can be used to launch a method when your bean is clicked.

So I tried it on my bean but unfortunately it seems to be a method of the DBTreeView bean only.

How could I reproduce this method? Or implement something which does what I need?

You must implement something similar. setMethodToCallOnClick stores in some class the details, then it is executed with application.executeMethod when event occurs. So, just add a listener to component for needed event and do application.executeMethod with the method you want.

lvostinar:
You must implement something similar. setMethodToCallOnClick stores in some class the details, then it is executed with application.executeMethod when event occurs. So, just add a listener to component for needed event and do application.executeMethod with the method you want.

Where is application.executeMethod called? Is possible to call it inside your bean?! :shock:
I know that you can call executeMethod using an Headless client but without I don’t know. :roll:

So, If I understand well, in the Bean’s main class (the one containing my JPanel), I’ll have something like that:

public void drop(DropTargetDropEvent dtde) {
   filesInfo = getDropResult();
   application.executeMethod(myMethod, ...);
   ...
}

In my Servoy form methods file I’ll have:

function myMethod()
{
   var  filesInfo = elements.bean_65.filesInfo;
   ...
   //sends files using filesInfo
}

implement IServoyBeanFactory to get the IClientPluginAccess (application) object, then call executeMethod from IClientPluginAccess

lvostinar:
implement IServoyBeanFactory to get the IClientPluginAccess (application) object, then call executeMethod from IClientPluginAccess

Ok :)

Which jars are needed to import these classes?! j2dbdev.jar?
And is that the ones located under “…\Servoy\application_server\lib” ?!

I’ve check the API and I didn’t found IServoyBeanFactory but IServoyAwareBean which doesn’t contain any method to create or access an IClientPluginAccess :roll:

EDIT: found it simply in com.servoy.j2db with the help of Eclipse :lol:

import j2db.jar from \application_server\lib

I’m a bit lost.
I’ve created my class with the methods to implement but I don’t know what to put inside and also how to provide a IClientPluginAccess object :?

import com.servoy.j2db.IServoyBeanFactory;
import com.servoy.j2db.plugins.IClientPluginAccess;
import com.servoy.j2db.ui.IComponent;

public class FilesDndBeanFactory implements IServoyBeanFactory {

	@Override
	public IComponent getBeanInstance(int arg0, IClientPluginAccess arg1,
			Object[] arg2) {
		
		return null;
	}

	@Override
	public String getName() {
		
		return null;
	}

}

you must implement method getBeanInstance to return your bean; you receive the IClientPluginAccess as parameter so store it for later use

I have now 3 class in 3 different files:

  • FilesDndBeanFactory the class I need to build to be able to execute a method from the form.
  • FileDndBean which defines the JPanel and its listeners methods implementation.
  • FileDndBeanInfo which defines which variable will be accessible by the form’s methods.

Ivostinar:
you must implement method getBeanInstance to return your bean

In fact, I don’t understand which class will be accessed by Servoy to build the bean in the form. Do I need to create an object FileDndBean into FilesDndBeanFactory to return it?

Ivostinar:
you receive the IClientPluginAccess as parameter so store it for later use

Does Servoy automatically send the IClientPluginAccess object as parameter when it builds the bean into the form?
Will that work then?

public class FilesDndBeanFactory implements IServoyBeanFactory {

	public IClientPluginAccess icpa;
	public FileDndBean fdb = new FileDndBean();
	public String  name = "MyBean";

	   @Override
	   public IComponent getBeanInstance(int arg0, IClientPluginAccess arg1,
	         Object[] arg2) {
	      icpa = arg1;
	      return (IComponent) fdb;
	   }

	public String getName() {
	      
	      return name;
	   }

	public void runMethod(String methodName, String arg0) {
	      
	      icpa.executeMethod(methodName,arg0,null);
	   }
}

yes, i think it should work

I’ve modified the code to make it work how I want. But now the bean is not valid. When I include it into my form, in Developer, it says:

error accessing bean myPackage.FileDndBeanFactory

Here is my code:
FileDndBeanFactory (main bean class):

public class FileDndBeanFactory implements IServoyBeanFactory {

	public IClientPluginAccess icpa;
	public FileDndBean fdb;
	public String  name = "MyBean";
	public String urlList = "NULL";
	public String methodName = "checkURL";

	@Override
	public IComponent getBeanInstance(int arg0, IClientPluginAccess arg1,
			Object[] arg2) {
		icpa = arg1;
		fdb = new FileDndBean(icpa, methodName);
		return (IComponent) fdb;
	}

	public String getName() {

		return name;
	}

	public String getUrlList() {
		return fdb.getUrlList();
	}

	public void setUrlList(String urlList) {
		fdb.setUrlList(urlList);
	}

	public String getMethodName() {
		return methodName;
	}

	public void setMethodName(String methodName) {
		this.methodName = methodName;
		
	}	
}

FileDnbBeanFactoryInfo:

public class FileDndBeanFactoryInfo
extends SimpleBeanInfo {

	public PropertyDescriptor[] getPropertyDescriptors()
	{
		try
		{
			PropertyDescriptor urlList = new PropertyDescriptor("urlList", FileDndBeanFactory.class);
			PropertyDescriptor methodName = new PropertyDescriptor("methodName", FileDndBeanFactory.class);
			PropertyDescriptor result[] = { urlList, methodName };
			return result;
		}
		catch (Exception ex)
		{
			System.out.println("InMemDataGridBeanInfo: unexpected exeption: " + ex); 
			return null;
		}
	}
}

FileDndBean (class containing the GUI + drop listener code):

public class FileDndBean extends JPanel implements DropTargetListener {

	private static final long serialVersionUID = 1L;

	DropTarget dt;

	JTextArea ta;
	String urlList;
	String methodName;
	IClientPluginAccess icpa;

	public FileDndBean(IClientPluginAccess icpa, String methodName) {
		super();
		this.icpa = icpa;
		urlList="NULL";
		this.methodName = methodName;
		
		ta = new JTextArea();
		ta.setRows(100);
		ta.setColumns(200);
		ta.setBackground(Color.white);
		add(ta);

		// Set up our text area to recieve drops...
		// This class will handle drop events
		dt = new DropTarget(ta, this);
		setVisible(true);
	}

	@SuppressWarnings("unchecked")
	public void drop(DropTargetDropEvent dtde) {
		try {
                            //...
			        //Code that get the files information to generate urlList
                            //...
					icpa.executeMethod(null,methodName, new String[]{urlList} , false);
				
					// If we made it this far, everything worked.
					dtde.dropComplete(true);
					return;
				}
			}
			System.out.println("Drop failed: " + dtde);
			dtde.rejectDrop();
		} catch (Exception e) {
			e.printStackTrace();
			dtde.rejectDrop();
		}
	}

	public String getUrlList() {
		return urlList;
	}

	public void setUrlList(String urlList) {
		this.urlList = urlList;
	}

	public String getMethodName() {
		return methodName;
	}

	public void setMethodName(String methodName) {
		this.methodName = methodName;
	}
}

MANIFEST.MF:

Manifest-Version: 1.0

Name: myPackage/FileDndBeanFactory.class
Java-Bean: True

Really hard to comment on…

IT2Be:
Really hard to comment on…

Here is the jar with the sources inside.
It will be maybe easier for you to look at it. :roll:

[attachment=0]FileDndBean.jar[/attachment]

FileDndBean.jar (6.8 KB)

error accessing bean myPackage.FileDndBeanFactory

This seems to be a package/path error. Is FileDndBeanFactory in package “myPackage” ?

lvostinar:
This seems to be a package/path error. Is FileDndBeanFactory in package “myPackage” ?

Yes, if you look at the jar I’ve posted in my previous reply, you will see that all the files are in the same package which corresponds to the MANIFEST package.

Are there any naming rules for beans file names?

I don’t get this error but i have in the log: java.lang.ClassCastException: com.assetguardian.FileDndBean cannot be cast to com.servoy.j2db.ui.IComponent . So, FileDndBean must implement IComponent. Also in manifest file you should have the bean not the factory: Name: com/assetguardian/FileDndBean.class . Change these, close developer, copy bean to beans folder then start developer again and see what happens.

lvostinar:
I don’t get this error but i have in the log: java.lang.ClassCastException: com.assetguardian.FileDndBean cannot be cast to com.servoy.j2db.ui.IComponent . So, FileDndBean must implement IComponent. Also in manifest file you should have the bean not the factory: Name: com/assetguardian/FileDndBean.class . Change these, close developer, copy bean to beans folder then start developer again and see what happens.

The problem is that with my code FileDndBeanFactory creates an instance of FileDndBean with the IClientPluginAccess object and the name of the method to run in the drop listener.
Will it work if I put FileDndBean as main bean class? I don’t really understand how Servoy proceeds to create the bean. Which object is created first?!

Which object is created first?!

You only use the factory to create your bean instance that will be used everywhere. You can use different instances for different types of application.

Will it work if I put FileDndBean as main bean class?

First you should have FileDndBean implement IComponent, I am not 100% which one will work.

It works now!!! :D

I have implemented IComponent in FileDndBean, changed the manifest to FileDndBean and that’s all :D

Only one last question for information. As my bean is attached to a form, I was thinking that it would call the method from the form. But in fact it call the method from the globals. Is that normal?

Thanks a lot Ivostinar for your help :wink:

Foobrother:
It works now!!! :D
Only one last question for information. As my bean is attached to a form, I was thinking that it would call the method from the form. But in fact it call the method from the globals. Is that norma

/**

  • Executes a method with methodname and arguments in the given context
  • If context is a formname a form method is executed, if null a global method will be assumed.
  • @return null if called with “true” for async flag, otherwise the method result is returned
    */
    public Object executeMethod(String context, String methodname, Object arguments,boolean async) throws Exception;

if context is null global method, else it is taken as form name