Archived

This forum has been archived. Please start a new discussion on GitHub.

Ice in java without stub instead of with annotation

Hi,
At First, I must be soooorry my english speaking and writing.
As you saw, Java and C# both handle annotations.
With slice2java we got a lot of classes, too many, is it?
And We must face to a problem that we cannot utilize exist java class until using delegate interactive with exist model.
Whether We can do a work like new EJB, without stub class and stub interface and stub exception, and without no big model changing?
Would there be a new slice2java compiler and a newer support library? Maybe a danamic proxy model or dynamic bytecode?

Regards

Comments

  • Welcome to our forums. Since the language of these forums is English, can you please add your signature information in English language as well? See this post for details.

    Also, I'm afraid we don't understand your question. Can you perhaps rephrase your question with an exact problem statement?
  • Right, I did change signature, But the post don't tell anybody whim can only use english.:)
    As I sayed before, please forgot my bad english.
    You could capture what I meaned If you got some oriental wisdom, haha, just a joke:)

    OK, let's go to main thread:
    I guess that you are familiar with java rmi.
    Java5 give developers an easy way to code, that is no need to run rmic.
    EJB3 give developers a similar way to code, and there is no need to declare RemoteException on interface in ejb3.
    Maybe Ice can do it without running slice2java.
    not only slice2java, but also maybe slice2c#.
    I don't know if the way is in your planning.

    Regards
  • I think you are proposing that Ice can do without Slice. Sorry, this won't happen. A separate interface specification language has many advantages. It is language neutral (how would you annotate C++?), and it gives you a higher level of abstraction. Mixing implementation with interface, in particular for cross-platform, multi-language projects, doesn't scale well. You would have to duplicate interface definition in all your implementations, which would become very chaotic over time.

    For more information about the Ice application development philosophy, I recommend to study the first chapters of our Ice user manual.
  • Thanks.:)
    No, I don't mean that Coding in Ice without Slice.
    I do mean that let slice generate a minimal size of stub or skeleton codes.
    I don't know how you handle difference between kinds of target language.
    From view of java(maybe c#), slice is similar with java definition.
    I hope like this:
    slice interface:
    interface hello{ void hi();};

    generated java:
    @slice
    public interface hello{ void hi();}

    then code in servant:
    public class HelloI implements hello{
    public void hi(){sysout("hi");}
    }

    adapter.add(new HelloI(), helloIdentity);

    code in client:
    ObjectPrx aop=communicator().stringToProxy(property);
    hello = IceProxy.checkcast(aop);
    hello.hi();

    So we can just and some annotations in existed java code.
    If just all in java, no need slice;
    if for other languages, just do slice definitions.

    Besides, if think about __current, maybe to put it Threadlocal is good idea for this way.

    What about it?

    Regards
  • marc wrote:
    I think you are proposing that Ice can do without Slice. Sorry, this won't happen. A separate interface specification language has many advantages. It is language neutral (how would you annotate C++?), and it gives you a higher level of abstraction. Mixing implementation with interface, in particular for cross-platform, multi-language projects, doesn't scale well. You would have to duplicate interface definition in all your implementations, which would become very chaotic over time.

    For more information about the Ice application development philosophy, I recommend to study the first chapters of our Ice user manual.

    Hi,Marc:
    Maybe Qinxian means that the generated code of slice2java can be simplified by using one new feature of java5: annotation.

    As the useage of annotation, this is one of my post: http://www.zeroc.com/vbulletin/showthread.php?t=2552

    So I am also an advocator of java5's annotation:) It can really simplify the generated code of slice2java.

    I am not familar with C#, so I have no comment of C#'s annotation in Qinxian's post.
  • Sorry, but I'm afraid I can't really write a full explanation here for why Ice doesn't work like this, as I would in essence have to explain everything that is already explained in the Ice manual. So my recommendation is to study the manual and the philosophy behind Ice.

    No doubt, you could write a middleware that is similar to what you propose, but Ice isn't such a middleware, for many reasons--all of them explained in the Ice manual :) I think what you are looking for is Java RMI, not Ice.
  • Hi, I do a simple work for annotation, based printString sample.
    //slice definition
    module demo{
    
    interface Printer{
    
    	void printString(string s);
    };
    };
    
    //Java annotation
    package ice;
    
    import static java.lang.annotation.ElementType.TYPE;
    import static java.lang.annotation.RetentionPolicy.RUNTIME;
    
    import java.lang.annotation.Retention;
    import java.lang.annotation.Target;
    
    /**
     * @author qinxian
     * @since 3.0
     */
    @Retention(RUNTIME)
    @Target(TYPE)
    public @interface IceIdentity {
    	String value();
    }
    
    package demo;
    
    import ice.IceIdentity;
    
    @IceIdentity("::demo::Printer")
    public interface Printer extends Ice.Object, _PrinterOperations, _PrinterOperationsNC {
    }
    
    //It's server tie style disp implemantation, just handler PrintString 
    package ice;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    import Ice.Current;
    import Ice.ObjectImpl;
    import Ice.TieBase;
    
    /**
     * @author qinxian
     * @since 3.0
     */
    public class ServerProxy implements InvocationHandler {
    	private ServerTie<?> tie;
    	private Class<?> interfaceClass;
    
    	/**
    	 * @param tie
    	 */
    	@SuppressWarnings("unchecked")
    	public ServerProxy(Class interfaceClass, Object ice_delegate, String[] ids, String[] all) {
    		super();
    		this.interfaceClass = interfaceClass;
    		tie = new ServerTie(ice_delegate, ids, all);
    	}
    
    	class ServerTie<T> extends ObjectImpl implements TieBase {
    		private T ice_delegate;
    		private String[] __ids;
    
    		/**
    		 * @param ice_delegate
    		 * @param __ids
    		 * @param __all
    		 */
    		public ServerTie(T ice_delegate, String[] ids, String[] all) {
    			super();
    			this.ice_delegate = ice_delegate;
    			this.__ids = ids;
    			this.__all = all;
    		}
    
    		public Object ice_delegate() {
    			return ice_delegate;
    		}
    
    		@SuppressWarnings("unchecked")
    		public void ice_delegate(Object delegate) {
    			this.ice_delegate = (T) delegate;
    		}
    
    		@Override
    		public boolean equals(java.lang.Object rhs) {
    			if (this == rhs) {
    				return true;
    			}
    			if (!(rhs instanceof ServerTie)) {
    				return false;
    			}
    
    			return ice_delegate.equals(((ServerTie) rhs).ice_delegate);
    		}
    
    		@Override
    		public int hashCode() {
    			return ice_delegate.hashCode();
    		}
    
    		protected void ice_copyStateFrom(Ice.Object __obj) throws java.lang.CloneNotSupportedException {
    			throw new java.lang.CloneNotSupportedException();
    		}
    
    		@Override
    		public boolean ice_isA(String s) {
    			return java.util.Arrays.binarySearch(__ids, s) >= 0;
    		}
    
    		@Override
    		public boolean ice_isA(String s, Ice.Current __current) {
    			return java.util.Arrays.binarySearch(__ids, s) >= 0;
    		}
    
    		@Override
    		public String[] ice_ids() {
    			return __ids;
    		}
    
    		@Override
    		public String[] ice_ids(Ice.Current __current) {
    			return __ids;
    		}
    
    		@Override
    		public String ice_id() {
    			return __ids[__ids.length - 1];
    		}
    
    		@Override
    		public String ice_id(Ice.Current __current) {
    			return __ids[__ids.length - 1];
    		}
    
    		private String[] __all;
    
    		@Override
    		public IceInternal.DispatchStatus __dispatch(IceInternal.Incoming in, Ice.Current __current) {
    			System.out.println(Arrays.asList(__all));
    			System.out.printf("%s, %s\n", __current.operation, __current.ctx);
    			int pos = java.util.Arrays.binarySearch(__all, __current.operation);
    			System.out.println(pos);
    			if (pos < 0) {
    				return IceInternal.DispatchStatus.DispatchOperationNotExist;
    			}
    			switch (pos) {
    				case 0 :
    					return ___ice_id(this, in, __current);
    				case 1 :
    					return ___ice_ids(this, in, __current);
    				case 2 :
    					return ___ice_isA(this, in, __current);
    				case 3 :
    					return ___ice_ping(this, in, __current);
    				default :
    					__checkMode(Ice.OperationMode.Normal, __current.mode);
    					IceInternal.BasicStream __is = in.is();
    					String s;
    					s = __is.readString();
    					try {
    						Method method = interfaceClass.getMethod(__all[pos], String.class, Current.class);
    						System.out.println(method);
    						method.invoke(ice_delegate, s, __current);
    						return IceInternal.DispatchStatus.DispatchOK;
    					} catch (Exception e) {
    						e.printStackTrace();
    					}
    			}
    
    			assert (false);
    			return IceInternal.DispatchStatus.DispatchOperationNotExist;
    		}
    
    	}
    
    	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    		Class declaringClass = method.getDeclaringClass();
    		String methodName = method.getName();
    		System.out.printf("%s.%s: args:%s\n", declaringClass, methodName, Arrays.asList(args));
    
    		if (declaringClass == TieBase.class || declaringClass == Ice.Object.class)
    			return method.invoke(tie, args);
    
    		if (declaringClass == interfaceClass) {
    			Object lastArg = null;
    			int len = args.length;
    			if (len > 0)
    				lastArg = args[len - 1];
    			if (lastArg instanceof Current) {
    			}
    			Object[] newArgs = new Object[len + 1];
    			System.arraycopy(args, 0, newArgs, 0, len);
    			newArgs[len] = lastArg;
    			return method.invoke(tie.ice_delegate, newArgs);
    		}
    		return method.invoke(tie.ice_delegate, args);
    	}
    
    	@SuppressWarnings("unchecked")
    	public static <T> Ice.Object proxy(Object impl, Class<T> interfaceClass) {
    		ClassLoader loader = impl.getClass().getClassLoader();
    
    		String[] ids = new String[2];
    		ids[0] = "::Ice::Object";
    		ids[1] = interfaceClass.getAnnotation(IceIdentity.class).value();
    
    		List<String> allMethods = new ArrayList<String>();
    		allMethods.addAll(Arrays.asList("ice_id", "ice_ids", "ice_isA", "ice_ping"));
    		String methodName = null;
    		for (Method method : interfaceClass.getMethods()) {
    			if (method.getDeclaringClass() == Ice.Object.class) {
    			} else {
    				methodName = method.getName();
    				if (allMethods.contains(methodName)) {
    				} else
    					allMethods.add(methodName);
    			}
    		}
    
    		ServerProxy h = new ServerProxy(interfaceClass, impl, ids, allMethods.toArray(new String[0]));
    
    		Class[] allInterfaces = new Class[3];
    		allInterfaces[0] = Ice.Object.class;
    		allInterfaces[1] = TieBase.class;
    		allInterfaces[2] = interfaceClass;
    
    		return (Ice.Object) Proxy.newProxyInstance(loader, allInterfaces, h);
    	}
    }
    
    To be continue:
  • //Client Proxy
    package ice;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.util.Arrays;
    import java.util.Map;
    
    import Ice.ObjectPrx;
    import Ice.ObjectPrxHelperBase;
    import Ice._ObjectDelD;
    import Ice._ObjectDelM;
    import IceInternal.LocalExceptionWrapper;
    
    /**
     * @author qinxian
     * @since 3.0
     */
    public class Helper<T> implements InvocationHandler {
    	private ObjectPrxHelperBase prxHelper;
    	private Class<T> interfaceClass;
    
    	// private static ThreadLocal<Map> ctx;
    	// private static ThreadLocal<Current> cur;
    
    	/**
    	 * @param prxHelper
    	 * @param interfaceClass
    	 */
    	public Helper(ObjectPrxHelperBase prxHelper, Class<T> interfaceClass) {
    		super();
    		this.prxHelper = prxHelper;
    		this.interfaceClass = interfaceClass;
    	}
    
    	@SuppressWarnings("unchecked")
    	private static <T> T proxyInstance(Class<T> interfaceClass, Helper<T> h) {
    		Class[] classes = new Class[] {ObjectPrx.class, interfaceClass};
    		return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), classes, h);
    	}
    
    	@SuppressWarnings("unchecked")
    	public static <T> T checkedCast(Ice.ObjectPrx __obj, Class<T> interfaceClass) {
    		T __d = null;
    		if (__obj != null) {
    			try {
    				__d = interfaceClass.cast(__obj);
    				System.out.println(__d);
    			} catch (ClassCastException ex) {
    				if (__obj.ice_isA(interfaceClass.getAnnotation(IceIdentity.class).value())) {
    					ProxyHelper __h = new ProxyHelper();
    					__h.__copyFrom(__obj);
    					Helper<T> helper = new Helper<T>(__h, interfaceClass);
    					__d = proxyInstance(interfaceClass, helper);
    				}
    			} catch (Exception e) {
    				e.printStackTrace();
    			}
    		}
    		return __d;
    	}
    
    	static class DelM extends _ObjectDelM implements Call {
    		public Object call(Class<?> servantClass, Method method, Object[] args, Map __ctx) throws LocalExceptionWrapper {
    			IceInternal.Outgoing __og = __connection.getOutgoing(__reference, method.getName(), Ice.OperationMode.Normal, __ctx, __compress);
    			try {
    				try {
    					IceInternal.BasicStream __os = __og.os();
    					Class<?> argClass = null;
    					for (Object arg : args) {
    						argClass = arg.getClass();
    						if (argClass == Ice.Object.class) {
    							__os.writeObject(Ice.Object.class.cast(arg));
    							__os.writePendingObjects();
    						}
    						if (argClass == String.class)
    							__os.writeString((String) arg);
    					}
    				} catch (Ice.LocalException __ex) {
    					__og.abort(__ex);
    				}
    				boolean __ok = __og.invoke();
    				try {
    					IceInternal.BasicStream __is = __og.is();
    					if (!__ok) {
    						try {
    							__is.throwException();
    						} catch (Ice.UserException __ex) {
    							throw new Ice.UnknownUserException(__ex.ice_name());
    						}
    					}
    					if (method.getReturnType() == Void.class)
    						return null;
    					return null;
    				} catch (Ice.LocalException __ex) {
    					throw new IceInternal.LocalExceptionWrapper(__ex, false);
    				}
    			} finally {
    				__connection.reclaimOutgoing(__og);
    			}
    
    		}
    	}
    
    	static class ProxyHelper extends ObjectPrxHelperBase {
    
    		@Override
    		protected Ice._ObjectDelM __createDelegateM() {
    			return new DelM();
    		}
    
    		@Override
    		protected Ice._ObjectDelD __createDelegateD() {
    			return new DelD();
    		}
    
    	}
    
    	interface Call {
    		Object call(Class<?> servantClass, Method method, Object[] args, Map __ctx) throws LocalExceptionWrapper;
    	}
    
    	static class DelD extends _ObjectDelD implements Call {
    		public Object call(Class<?> servantClass, Method method, Object[] args, Map __ctx) throws LocalExceptionWrapper {
    			Ice.Current __current = new Ice.Current();
    			__initCurrent(__current, method.getName(), Ice.OperationMode.Normal, __ctx);
    			while (true) {
    				IceInternal.Direct __direct = new IceInternal.Direct(__current);
    				try {
    					Object __servant = null;
    					try {
    						__servant = __direct.servant();
    					} catch (ClassCastException __ex) {
    						Ice.OperationNotExistException __opEx = new Ice.OperationNotExistException();
    						__opEx.id = __current.id;
    						__opEx.facet = __current.facet;
    						__opEx.operation = __current.operation;
    						throw __opEx;
    					}
    					try {
    						int len = args.length;
    						Object[] newArgs = new Object[len + 1];
    						System.arraycopy(args, 0, newArgs, 0, len);
    						newArgs[len] = __current;
    						// return __servant.echo(x, __current);
    						return method.invoke(__servant, args);
    					} catch (InvocationTargetException ite) {
    						ite.printStackTrace();
    					} catch (IllegalAccessException iae) {
    						iae.printStackTrace();
    						// throw new LocalExceptionWrapper(iae, false);
    					} catch (Ice.LocalException __ex) {
    						throw new IceInternal.LocalExceptionWrapper(__ex, false);
    					}
    				} finally {
    					__direct.destroy();
    				}
    			}
    
    		}
    	}
    
    	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    		String methodName = method.getName();
    		System.out.printf("%s.%s, args:=%s\n", method.getDeclaringClass(), methodName, Arrays.asList(args));
    		// if (method.getDeclaringClass() == interfaceClass)
    		Map __ctx = null;
    		int __cnt = 0;
    		while (true) {
    			try {
    				if (method.getReturnType() != Void.class)
    					prxHelper.__checkTwowayOnly(methodName);
    				Ice._ObjectDel __delBase = prxHelper.__getDelegate();
    				System.out.println(__delBase);
    				// ctx.set(ophb.ice_getContext());
    				__ctx = prxHelper.ice_getContext();
    				Call call = (Call) __delBase;
    				return call.call(interfaceClass, method, args, __ctx);
    			} catch (LocalExceptionWrapper __ex) {
    				prxHelper.__handleExceptionWrapper(__ex);
    			} catch (Ice.LocalException __ex) {
    				__cnt = prxHelper.__handleException(__ex, __cnt);
    			}
    		}
    	}
    }
    
    Server application
    public class PrintIApplication extends Application implements Runnable {
    	public void run() {
    		communicator().shutdown();
    	}
    
    	@Override
    	public int run(String[] arg0) {
    		ObjectAdapter adapter = communicator().createObjectAdapter("Printer");
    		Identity id = communicator().stringToIdentity("printer");
    		// adapter.add(new PrintI(), id);
    		Ice.Object impl = ServerProxy.proxy(new PrinterImpl(), Printer.class);
    		adapter.add(impl, id);
    		adapter.activate();
    		communicator().waitForShutdown();
    		return 0;
    	}
    
    	public static void main(String[] args) {
    		// System.setProperty("javax.net.debug", "ssl");
    		PrintIApplication server = new PrintIApplication();
    		Thread consoleHook = new Thread(new ConsoleHook(server));
    		consoleHook.start();
    
    		int status = server.main("Server", args, "config.server");
    		try {
    			consoleHook.join();
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    		System.exit(status);
    	}
    }
    
    client Application
    public class PrintClientApplication extends Application {
    
    	@Override
    	public int run(String[] arg0) {
    		Ice.Properties prop = communicator().getProperties();
    		final String prxProperty = "Printer.Proxy";
    		String prox = prop.getProperty(prxProperty);
    		if (prox.length() == 0) {
    			System.out.println("not set");
    			return 1;
    		}
    		ObjectPrx __obj = communicator().stringToProxy(prox);
    		PrinterPrx pp = PrinterPrxHelper.checkedCast(__obj.ice_twoway().ice_timeout(-1).ice_secure(true));
    		pp.printString("hello");
    		pp = PrinterPrxHelper.checkedCast(__obj.ice_secure(true));
    		pp.printString("hello2");
    		if (pp == null) {
    			System.out.println("not invalid");
    			return 1;
    		}
    		PrinterPrx oneway = PrinterPrxHelper.uncheckedCast(pp.ice_oneway());
    		oneway.printString("haha&#31206;&#36132;");
    
    		Printer printer = Helper.checkedCast(__obj, Printer.class);
    		printer.printString("new helper");
    		return 0;
    	}
    
    	public static void main(String[] args) {
    		PrintClientApplication client = new PrintClientApplication();
    		int status = client.main("Client", args, "config.client");
    		System.exit(status);
    	}
    }
    
    I do test for printString;
    it works, and C++ client works.
  • Not complete, but it's a bird.
    So there are some files:
    ServerProxy(server)
    Helper(client)

    Interface(can be java native with annotations)
    and a Interface Implementation.
    last 2 files always needed.

    maybe few generic holder class.

    If slice in java like this way, jee would be dead for eeeever.:):D

    From my view, maybe java2slice is a better way.:)

    Welcome discuss.

    Regards