| At line 1 changed 1 line. | 
| ''Please note that in integrating of Spring Rich Client Project I havent yet solved all problems. But I hope my experiences should be usefull for anyone interested in this. Any sugestions solving some problems will be very appreciated.'' | 
| ''Please note that this tutorial is under development and there are still some unsolved issues. If you find solutions to any of them I would very much appreciate your help. Contact: [Radim Burget|RadimBurget]'' | 
| At line 3 changed 2 lines. | 
| !!! About Spring-rcp | 
| The goal of the [spring-richclient project|http://www.springframework.org/spring-rcp] is to provide a viable option for developers that need a platform and a 'best-practices' guide forconstructing professional Swing applications quickly. | 
| !Table of Contents | 
| * [1] About Spring-rcp | 
| * [2] Configuring Appfuse - map servlet to be listening on "ws/*" url address | 
| * [3] Configuring Appfuse - create ws servlet | 
| * [4] Configuring Appfuse - add *.jar library dependencies | 
| * [5] Configuring Appfuse - add interface to allow remote client logins | 
| At line 6 removed 1 line. | 
| My work is based on Spring-rcp Petclinic Demo (in [CVS|http://sourceforge.net/cvs/?group_id=113660] only) is  | 
| At line 11 added 6 lines. | 
| * [6] Configuring RichClient - source code | 
| * [7] Configuring RichClient - libraries | 
| * [8] Unsolved issues | 
| ---- | 
| !!! About Spring-rcp [#1] | 
| The goal of the [spring-richclient project|http://www.springframework.org/spring-rcp] is to provide a viable option for developers that need a platform and 'best-practices' guide for constructing professional Swing applications quickly. | 
| At line 18 added 1 line. | 
| My work is based on the Spring-rcp Pet Clinic Demo (in [CVS|http://sourceforge.net/cvs/?group_id=113660] only) and my efforts in integrating it with Appfuse. | 
| At line 20 added 3 lines. | 
| %%(border: 1px solid black; margin: 0 auto; height: 380px; width: 455px) | 
| [RichClient/screenshot1.jpg] | 
| %% | 
| At line 24 added 274 lines. | 
| !!! Configuring Appfuse - map servlet to be listening on "ws/*" url address [#2] | 
| Add this portion of code to metadata/web/__servlets.xml__  | 
| <div style="margin-left: 40px"> | 
| {{{ | 
|     <!-- REMOTE ACCESS SERVELTET --> | 
| 	<servlet> | 
| 		<servlet-name>ws</servlet-name> | 
| 		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> | 
| 		<load-on-startup>2</load-on-startup> | 
| 	</servlet> | 
 | 
|  	<!-- | 
| 	  - Dispatcher servlet mapping for HTTP web services. | 
| 	  - (see ws-servlet.xml for the controllers). | 
| 	  --> | 
| 	<servlet-mapping> | 
| 		<servlet-name>ws</servlet-name> | 
| 		<url-pattern>/ws/*</url-pattern> | 
| 	</servlet-mapping> | 
| }}} | 
| </div> | 
 | 
| !!! Configuring Appfuse - create ws servlet[#3] | 
| Create a ws servlet XML beans descriptor. Because I am using [Hessian|http://www.caucho.com/hessian/] instead of [Burlap|http://www.caucho.com/burlap/burlap.xtp] I have commented out Burlap-specific portions of the code. If you ever want to use Burlap instead just uncomment this part of the code. | 
 | 
| The main difference between Hessian and Burlap is that Hessian is binary and Burlap is XML-based. | 
| <div style="margin-left: 40px"> | 
| {{{ | 
| <?xml version="1.0" encoding="UTF-8" ?> | 
| <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> | 
 | 
| <!-- | 
|   - $Id: ws-servlet.xml,v 1.1 2004/08/01 23:03:20 benalex Exp $ | 
|   --> | 
| <beans> | 
 | 
| 	<!-- Hessian exporter for the Clinic --> | 
| 	<!-- Hessian is a slim binary HTTP remoting protocol --> | 
| 	<bean name="/Clinic-hessian" class="org.springframework.remoting.caucho.HessianServiceExporter"> | 
| 		<property name="service"><ref bean="userManager"/></property> | 
| 		<property name="serviceInterface"> | 
| 			<value>org.appfuse.service.UserManager</value> | 
| 		</property> | 
| 	</bean> | 
 | 
| 	<!-- Burlap exporter for the Clinic --> | 
| 	<!-- Burlap is a slim XML-based HTTP remoting protocol --> | 
| 	<!--bean name="/Clinic-burlap" class="org.springframework.remoting.caucho.BurlapServiceExporter"> | 
| 		<property name="service"><ref bean="clinic"/></property> | 
| 		<property name="serviceInterface"> | 
| 			<value>org.springframework.samples.petclinic.Clinic</value> | 
| 		</property> | 
| 	</bean--> | 
 | 
| 	<!-- Hessian exporter for the RemoteAuthenticationManager --> | 
| 	<bean name="/RemoteAuthenticationManager-hessian" class="org.springframework.remoting.caucho.HessianServiceExporter"> | 
| 		<property name="service"><ref bean="remoteAuthenticationManager"/></property> | 
| 		<property name="serviceInterface"> | 
| 			<value>net.sf.acegisecurity.providers.rcp.RemoteAuthenticationManager</value> | 
| 		</property> | 
| 	</bean> | 
 | 
| 	<!-- Burlap exporter for the RemoteAuthenticationManager --> | 
| 	<!--bean name="/RemoteAuthenticationManager-burlap" class="org.springframework.remoting.caucho.BurlapServiceExporter"> | 
| 		<property name="service"><ref bean="remoteAuthenticationManager"/></property> | 
| 		<property name="serviceInterface"> | 
| 			<value>net.sf.acegisecurity.providers.rcp.RemoteAuthenticationManager</value> | 
| 		</property> | 
| 	</bean--> | 
 | 
| </beans> | 
| }}} | 
| </div> | 
 | 
| !!! Configuring Appfuse - add *.jar library dependencies [#4] | 
 | 
| For more details read [how to add a library into appfuse|http://raibledesigns.com/wiki/Wiki.jsp?page=AppFuseAddLibrary] here. | 
 | 
| Copy hessian.jar to appfuse/lib/hessian/hessian.jar | 
 | 
| In lib/lib.properties add path info: | 
 | 
| <div style="margin-left: 40px"> | 
| {{{ | 
 | 
|   # | 
|   # Hessian | 
|   # | 
|   hessian.version=0.1 | 
|   hessian.dir=${lib.dir}/hessian-${hessian.version} | 
|   hessian.jar=${hessian.dir}/hessian-${hessian.version}.jar | 
| }}} | 
| </div> | 
 | 
| If you will ever need burlap do the same with the burlap *.jar files. | 
 | 
| Add to __build.xml__ the hessian library dependency: | 
| <div style="margin-left: 40px"> | 
| {{{ | 
| <target name="package-web" ...... | 
| ....... | 
| ......  | 
| <lib file="${hessian.jar}"/>  | 
| ......  | 
| </target>  | 
| }}} | 
| </div> | 
 | 
| (properties.xml does not need any changes) | 
 | 
| !!!Configuring Appfuse - add interface to allow remote client logins[#5] | 
 | 
| Add this bean to web/WEB-INF/__applicationContextSecurity.xml__: | 
 | 
| <div style="margin-left: 40px"> | 
| {{{ | 
| <!-- Allows remote clients to check if a username/password is valid --> | 
| <bean id="remoteAuthenticationManager" class="net.sf.acegisecurity.providers.rcp.RemoteAuthenticationManagerImpl">   | 
|       <property name="authenticationManager"><ref bean="authenticationManager"/></property> | 
| </bean> | 
| }}} | 
| </div> | 
 | 
| !!! Configuring RichClient - source code[#6] | 
 | 
| Download the [Appfuse Rich Client source code|http://raibledesigns.com/wiki/attach?page=RichClient%2Fappfuse-richclient.zip] and copy them to your Appfuse project. | 
 | 
| %%note __NOTE__ At first I tried to create a new standalone project that referenced the Appfuse project but was independent from it. Unfortunately I had some issues with compilation so I decided to integrate it directly to the project.%% | 
 | 
| !!! Configuring RichClient - libraries [#7] | 
 | 
| You will need to download these jar archives and add them to the Eclipse classpath (Eclipse: Project/Properties/Java Build Path/Libraries/Add JARs).  Be sure not to forget to refresh the appfuse directory structure afterwards. | 
| <div style="margin-left: 40px"> | 
| {{{ | 
| appfuse/lib  | 
|     /caucho | 
|         (84 871) burlap.jar | 
|         (83 245) hessian.jar | 
|     /jgoodies | 
|         (85 502)  forms.jar | 
|         (338 486) looks.jar | 
|     /spring-rcp | 
|         (366 615) spring-richclient-resources.jar | 
|          (59 691) spring-richclient-sandbox.jar | 
|         (736 813) spring-richclient.jar | 
|     /javahelp | 
|         (531 676) javahelp.jar | 
|     /spring | 
|         (741 379) spring-sandbox.jar | 
| }}} | 
| </div> | 
 | 
| My collection of JAR files can be downloaded from [here|http://raibledesigns.com/wiki/attach?page=RichClient%2Flib.zip]. | 
 | 
| Now you should be able to compile and run your application (org.appfuse.richclient.PetClinicClientServer) | 
 | 
| %%note __NOTE:__ Please ensure that your server is running ([http://localhost:8080/appfuse/ws/Clinic-hessian| http://localhost:8080/appfuse/ws/Clinic-hessian] displays exception "HessianServiceExporter only supports POST requests")%% | 
 | 
| !!! Unsolved issues [#8] | 
 | 
| ** On successfull login is thrown Exception ClassNotFoundException: net.sf.acegisecurity.context.SecureContextImpl | 
| ** on __userManager.getUsers(null)__ exception : | 
| org.hibernate.LazyInitializationException | 
 | 
| !! ClassNotFoundException | 
 | 
| Username is not yet crypted so I recomend to add new user to your database with __username__:test, __password__:test. | 
 | 
| On unsuccessful login everything is OK and is shown "Bad Credentials" message. | 
| On unsuccessfull login is thrown exception - In each appfusem 1.8 is in classpath included __lib\spring-1.2-rc2\acegi-security-0.8.2.jar__ which contains net.sf.acegisecurity.context.security.__SecureContextImpl__ class so I dont know where should be the problem :( | 
 | 
| <div style="margin-left: 40px"> | 
| {{{ | 
| java.lang.NoClassDefFoundError | 
 | 
|         at org.springframework.richclient.security.SessionDetails.class$(SessionDetails.java:97) | 
|         at org.springframework.richclient.security.SessionDetails.getSecureContextClass(SessionDetails.java:97) | 
|         at org.springframework.richclient.security.SessionDetails.login(SessionDetails.java:110) | 
|         at org.springframework.richclient.security.LoginForm.commit(LoginForm.java:57) | 
|         at org.springframework.richclient.security.LoginCommand$1.onFinish(LoginCommand.java:79) | 
|         at org.springframework.richclient.dialog.ApplicationDialog$1.doExecuteCommand(ApplicationDialog.java:322) | 
|         at org.springframework.richclient.command.ActionCommand.execute(ActionCommand.java:188) | 
|         at org.springframework.richclient.command.ActionCommand$1.actionPerformed(ActionCommand.java:123) | 
|         at javax.swing.AbstractButton.fireActionPerformed(Unknown Source) | 
|         at javax.swing.AbstractButton$ForwardActionEvents.actionPerformed(Unknown Source) | 
|         at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source) | 
|         at javax.swing.DefaultButtonModel.setPressed(Unknown Source) | 
|         at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source) | 
|         at java.awt.Component.processMouseEvent(Unknown Source) | 
|         at java.awt.Component.processEvent(Unknown Source) | 
|         at java.awt.Container.processEvent(Unknown Source) | 
|         at java.awt.Component.dispatchEventImpl(Unknown Source) | 
|         at java.awt.Container.dispatchEventImpl(Unknown Source) | 
|         at java.awt.Component.dispatchEvent(Unknown Source) | 
|         at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source) | 
|         at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source) | 
|         at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source) | 
|         at java.awt.Container.dispatchEventImpl(Unknown Source) | 
|         at java.awt.Window.dispatchEventImpl(Unknown Source) | 
|         at java.awt.Component.dispatchEvent(Unknown Source) | 
|         at java.awt.EventQueue.dispatchEvent(Unknown Source) | 
|         at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source) | 
|         at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) | 
|         at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) | 
|         at java.awt.Dialog$1.run(Unknown Source) | 
|         at java.awt.event.InvocationEvent.dispatch(Unknown Source) | 
|         at java.awt.EventQueue.dispatchEvent(Unknown Source) | 
|         at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source) | 
|         at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) | 
|         at java.awt.EventDispatchThread.pumpEvents(Unknown Source) | 
|         at java.awt.EventDispatchThread.pumpEvents(Unknown Source) | 
|         at java.awt.EventDispatchThread.run(Unknown Source) | 
 | 
| Caused by: java.lang.ClassNotFoundException: net.sf.acegisecurity.context.SecureContextImpl | 
 | 
|         at java.net.URLClassLoader$1.run(Unknown Source) | 
|         at java.security.AccessController.doPrivileged(Native Method) | 
|         at java.net.URLClassLoader.findClass(Unknown Source) | 
|         at java.lang.ClassLoader.loadClass(Unknown Source) | 
|         at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source) | 
|         at java.lang.ClassLoader.loadClass(Unknown Source) | 
|         at java.lang.ClassLoader.loadClassInternal(Unknown Source) | 
|         at java.lang.Class.forName0(Native Method) | 
|         at java.lang.Class.forName(Unknown Source) | 
|         ... 37 more | 
| }}} | 
| </div> | 
 | 
| !! LazyInitializationException | 
 | 
| <div style="margin-left: 40px"> | 
| {{{ | 
| org.hibernate.LazyInitializationException: failed to lazily initialize a collection  - no session or session was closed | 
|     at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:180) | 
|     at org.hibernate.collection.AbstractPersistentCollection.write(AbstractPersistentCollection.java:61) | 
|     at org.hibernate.collection.PersistentSet.add(PersistentSet.java:158) | 
|     at com.caucho.hessian.io.CollectionDeserializer.readList(CollectionDeserializer.java:97) | 
|     at com.caucho.hessian.io.HessianInput.readObject(HessianInput.java:674) | 
|     at com.caucho.hessian.io.JavaDeserializer.readMap(JavaDeserializer.java:135) | 
|     at com.caucho.hessian.io.JavaDeserializer.readMap(JavaDeserializer.java:114) | 
|     at com.caucho.hessian.io.SerializerFactory.readMap(SerializerFactory.java:147) | 
|     at com.caucho.hessian.io.HessianInput.readObject(HessianInput.java:781) | 
|     at com.caucho.hessian.io.CollectionDeserializer.readList(CollectionDeserializer.java:97) | 
|     at com.caucho.hessian.io.HessianInput.readObject(HessianInput.java:678) | 
|     at com.caucho.hessian.io.HessianInput.readReply(HessianInput.java:241) | 
|     at com.caucho.hessian.client.HessianProxy.invoke(HessianProxy.java:179) | 
|     at $Proxy0.getUsers(Unknown Source) | 
|     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) | 
|     at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) | 
|     at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) | 
|     at java.lang.reflect.Method.invoke(Unknown Source) | 
|     at org.springframework.remoting.caucho.HessianClientInterceptor.invoke(HessianClientInterceptor.java:115) | 
|     at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:144) | 
|     at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:174) | 
|     at $Proxy1.getUsers(Unknown Source) | 
|     at org.appfuse.richclient.ui.OwnerManagerView.createOwnerManagerTree(OwnerManagerView.java:127) | 
|     at org.appfuse.richclient.ui.OwnerManagerView.createControl(OwnerManagerView.java:117) | 
|     at org.springframework.richclient.factory.AbstractControlFactory.getControl(AbstractControlFactory.java:48) | 
|     at org.springframework.richclient.application.support.DefaultApplicationPage.createPageComponent(DefaultApplicationPage.java:71) | 
|     at org.springframework.richclient.application.support.AbstractApplicationPage.showView(AbstractApplicationPage.java:155) | 
|     at org.springframework.richclient.application.support.AbstractApplicationPage.showView(AbstractApplicationPage.java:186) | 
|     at org.springframework.richclient.application.support.DefaultApplicationPage.addView(DefaultApplicationPage.java:78) | 
|     at org.springframework.richclient.application.support.SingleViewPageDescriptor.buildInitialLayout(SingleViewPageDescriptor.java:60) | 
|     at org.springframework.richclient.application.support.DefaultApplicationPage.getControl(DefaultApplicationPage.java:45) | 
|     at org.springframework.richclient.application.support.DefaultApplicationWindow.applyCustomLayout(DefaultApplicationWindow.java:235) | 
|     at org.springframework.richclient.application.support.DefaultApplicationWindow.initWindowControl(DefaultApplicationWindow.java:220) | 
|     at org.springframework.richclient.application.support.DefaultApplicationWindow.initWindow(DefaultApplicationWindow.java:210) | 
|     at org.springframework.richclient.application.support.DefaultApplicationWindow.showPage(DefaultApplicationWindow.java:151) | 
|     at org.springframework.richclient.application.Application.openWindow(Application.java:163) | 
|     at org.springframework.richclient.application.ApplicationLauncher.launchMyRichClient(ApplicationLauncher.java:178) | 
|     at org.springframework.richclient.application.ApplicationLauncher.<init>(ApplicationLauncher.java:100) | 
|     at org.appfuse.richclient.PetClinicClientServer.main(PetClinicClientServer.java:41) | 
| }}} | 
| </div> |