RhoConnect-Java === The RhoConnect-Java library is designed for the [RhoConnect](http://rhomobile.com/products/rhoconnect/) Application Integration Server. Using the RhoConnect-Java plugin jar file, your [Spring 3 MVC](http://www.springsource.org/) application's data will transparently synchronize with a mobile application built on the [Rhodes framework](http://rhomobile.com/products/rhodes), or any of the available [RhoConnect clients](http://rhomobile.com/products/rhoconnect/). image ## Prerequisites * Java (1.6) * Maven2 (2.2.1) * Git * [Rhoconnect-java](https://github.com/downloads/rhomobile/rhoconnect-java/rhoconnect-java-1.0.1.jar) plugin jar file ## Getting Started We assume that you have a complete java end-to-end application using Spring 3.0 MVC as the front end technology and Hibernate as the backend ORM. For this application, we will also use Maven2 for build and dependency management and a database to persist the data. The database is accessed by a Data Access (DAO) layer. ## A Sample Java Spring 3.0 MVC Backend Application The instructions in the following steps show how to install the `rhoconnect-java` plugin jar file into an existing Java end-to-end application using Sprint 3.0 MVC as the front end technology, and Hibernate as the backend ORM. For an example, you can download and install the [RhoconnectJavaSample](https://github.com/shurab/RhoconnectJavaSample) application. This sample Java application was created using Sprint 3.0 MVC, using [this tutorial to Create Spring 3 MVC Hibernate 3 Example using Maven in Eclipse](http://viralpatel.net/blogs/2010/11/spring3-mvc-hibernate-maven-tutorial-eclipse-example.html). To install this sample application, navigate in your web browser to [https://github.com/shurab/RhoconnectJavaSample](https://github.com/shurab/RhoconnectJavaSample) and download it as a zip file. Unzip it and rename the unzipped folder to RhoconnectJavaSample. Navigate into the `RhoconnectJavaSample` folder and run these commands to run the sample Java application. :::term $ mvn clean $ mvn jetty:run When you see `[INFO] Started Jetty Server`, open a web browser and navigate to `http://localhost:8080/contacts/index` to see this application running. ## Settings for the Client App Your client application needs to have its model match the model used in your Java Sprint 3.0 MVC backend application. For example, you can generate a Rhodes application for a Contact model to match the RhoconnectJavaSample application: :::term $ rhodes app contact-app $ cd contact-app $ rhodes model contact lastname,firstname,email,telephone Edit the `rhoconfig.txt` configuration file to point to your RhoConnect server, where is the url for your RhoConnect server. :::term syncserver = 'http:///application' And edit the `app/index.erb` view file to say Contacts: :::html ...
  • Contacts
  • ... And edit `app/Contact/contact.rb` file to enable sync. :::ruby ... enable :sync ... ## Settings for the RhoConnect Server App You must generate a RhoConnect server application and edit its settings for the RhoConnect Java plugin. :::term $ rhoconnect app syncserver $ cd syncserver; bundle install Edit the `settings/settings.yml` development section to add an api\_token key/value pair. This value is the same as the api\_token that you will set in the `WEB-INF/spring-servlet.xml` file for your Java backend application. :::term :development: ... :api_token: rhoconnect_api_token ## Adding Dependencies to Your Java Application Maven 2 POM Add dependencies to the Apache Maven 2 project object model (POM) in your Java application by plugging the code below into the `pom.xml` file. This adds dependencies for log4j, Apache common beanutils, and Jackson JSON mapper. :::xml log4j log4j 1.2.9 jar false commons-beanutils commons-beanutils 1.8.3 org.codehaus.jackson jackson-mapper-asl 1.9.0 jar false ## Adding the rhoconnect-java Plugin Jar File to Your Java Backend Application At this time, the rhoconnect-java plugin jar file is not available in Maven public repositories, so you need to manually install this jar into your Maven's local repository. Download the [Rhoconnect-java](https://github.com/downloads/rhomobile/rhoconnect-java/rhoconnect-java-1.0.1.jar) plugin jar file to your PC. Use the following Maven command to add the rhoconnect-java plugin jar file to your Java backend application. Replace `path-to-jar` with the path to where you have the rhoconnect-java plugin jar file. :::term $ mvn install:install-file -Dfile=/path-to-jar/rhoconnect-java-1.0.1.jar -DgroupId=com.rhomobile.rhoconnect -DartifactId=rhoconnect-java -Dversion=1.0.1 -Dpackaging=jar Now that the rhoconnect-java jar library is included in your Maven local repository, you must add it as a dependency by adding the following code to the `pom.xml` file. Make sure the version number matches the version number in the jar file name. :::xml com.rhomobile.rhoconnect rhoconnect-java 1.0.1 jar ### Creating the rhoconnect-java Plugin Jar File from the rhoconnect-java Repository Instead of downloading the rhoconnect-java plugin jar file, you can generate it from sources by cloning the `rhoconnect-java` repository: :::term $ git clone https://github.com/rhomobile/rhoconnect-java.git and executing the following commands in your cloned rhoconnect-java project directory: :::term $ mvn clean $ mvn compile $ mvn jar:jar The archived `rhoconnect-java-x.y.z.jar` file will be created in the project's `target` directory. ## Updating Your Servlet XML Configuration File Update your servlet xml configuration file in your Java backend application folder to include rhoconnect-java metadata: the packages, converters, and beans. In your Java application folder (such as the RhoconnectJavaSample folder), add the following code to `src/main/webapp/WEB-INF/spring-servlet.xml`. :::xml ### Configuring Properties in the setAppEndpoint Method The `setAppEndpoint` method in the `rhoconnectClient` bean in the above code sample is a main point in establishing the communication link between the `Rhoconnect` server and your Java Spring 3 MVC backend application. It has the following properties that you need to configure.
    your_rhoconnect_server_url rhoconnect server's url, for example http://localhost:9292
    app_endpoint_url your Spring 3 MVC app url, for example http://localhost:8080/contacts
    apiToken rhoconnect server's api_token, for example rhoconnect_api_token
    The `authenticate` bean will be called by the RhoConnect server to authenticate users, so it has to implement the `Rhoconnect` interface provided by the rhoconnect-java plugin: :::java package com.rhomobile.rhoconnect; import java.util.Map; public interface Rhoconnect { String authenticate(String userName, String password, Map attributes); } For example, in the RhoConnectJavaSample example, in `src/main/java/com/rhomobile/contact/ContactAuthenticate.java`, you can code the ContactAuthentication class as follows, replacing the TODO comment with authentication code (this example just returns "app"). :::java package com.rhomobile.contact; import java.util.Map; import org.apache.log4j.Logger; import com.rhomobile.rhoconnect.Rhoconnect; public class ContactAuthenticate implements Rhoconnect { private static final Logger logger = Logger.getLogger(ContactAuthenticate.class); @Override public String authenticate(String login, String password, Map attributes) { logger.debug("ContactAuthenticate#authenticate: implement your authentication code!"); // TODO: your authentication code goes here ... // Return null value if authentication fails. // Otherwise, returned value is data partitioning: i.e. user name for filtering data on per user basis //return login; // But if you want your data to be partitioned by 'app' (i.e. the data will be shared among all users), // you should return string "app": it will instruct Rhoconnect to partition the data accordingly. return "app"; } } ## Establishing communication from the RhoConnect server to the java backend application You need to establish communication from the RhoConnect instance to your java backend application by mixing the RhoconnectResource interface in your data access (DAO) service class. This interface is in the Java plugin, `rhoconnect-java/src/main/java/com/rhomobile/rhoconnect/RhoconnectResource.java`. (Note that you do not change the code in `RhoconnectResource.java`.) :::java package com.rhomobile.rhoconnect; import java.util.Map; public interface RhoconnectResource { Map rhoconnectQuery(String partition); Integer rhoconnectCreate(String partition, Map attributes); Integer rhoconnectUpdate(String partition, Map attributes); Integer rhoconnectDelete(String partition, Map attributes); } To help the rhoconnect-java plugin correctly map the model name to the service bean, you should take into account the following conventions when you write the code in your Java backend application to establish communication to the RhoConnect server: * The name of the DAO service bean (class) in your java backend application should be the model name followed by `ServiceImpl` suffix (i. e. `ContactServiceImpl` for model `Contact`) * The service bean should be auto-wired into the corresponding controller via @Autowired annotation Data partitioning in your code should be based on filtering data for unique user (i.e. your user name) or per application (shared dataset for all users). For more information about RhoConnect partitions, please refer to the [RhoConnect docs](http://docs.rhomobile.com/rhoconnect/source-adapters#data-partitioning). ## Establishing communication from java backend application to the RhoConnect server You must establish the communication from your java backend application to the RhoConnect server by auto-wiring the `RhoconnectClient` bean into your DAO service class and inserting notifications hooks into the data access (create/update/delete) methods. After you generate a Sprint 3.0 MVC application, you have a DAO service class similar to the RhoconnectJavaSample file of `ContactServiceImpl.java`, located in `src/main/java/com/rhomobile/contact/service`. :::java package com.rhomobile.contact.service; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.rhomobile.contact.dao.ContactDAO; import com.rhomobile.contact.form.Contact; @Service public class ContactServiceImpl implements ContactService { @Autowired private ContactDAO contactDAO; @Transactional public int addContact(Contact contact) { return contactDAO.addContact(contact); } @Transactional public List listContact() { return contactDAO.listContact(); } @Transactional public void removeContact(Integer id) { contactDAO.removeContact(id); } @Transactional public Contact getContact(Integer id) { return contactDAO.getContact(id); } @Transactional public void updateContact(Contact contact) { contactDAO.updateContact(contact); } } `RhoconnectClient` bean is provided by rhoconnect-java plugin and responds to the following methods you have to call: * boolean notifyOnCreate(String sourceName, Object objId, Object object) * boolean notifyOnUpdate(String sourceName, Object objId, Object object) * boolean notifyOnDelete(String sourceName, Object objId) Here is an example of how you would recode the ContactServiceImpl.java for the `RhoconnectJavaSample` application. Comments are added to show where you add new code to import libraries such as `RhoconnectClient` and `RhoconnectResource`, and where you call the notifyOnCreate, notifyOnDelete, and notifyOnUpdate methods to tell the backend about changes from the RhoConnect server, and where you implement the rhoconnectQuery, rhoconnectCreate, rhoconnectUpdate, and rhoconnectDelete methods to communicate changes in the backend to the RhoConnect server. :::java package com.rhomobile.contact.service; import java.util.HashMap; /* import HashMap */ import java.util.Iterator; /* import Iterator */ import java.util.List; import java.util.Map; /* import Map */ import org.apache.commons.beanutils.BeanUtils; /* import BeanUtils */ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.rhomobile.contact.dao.ContactDAO; import com.rhomobile.contact.form.Contact; /* import RhoconnectClient bean and RhoconnectResource bean */ import com.rhomobile.rhoconnect.RhoconnectClient; import com.rhomobile.rhoconnect.RhoconnectResource; /* add RhoConnectResource to class implementation */ @Service public class ContactServiceImpl implements ContactService, RhoconnectResource { //private static final Logger logger = Logger.getLogger(ContactServiceImpl.class); @Autowired private ContactDAO contactDAO; /* Add the RhoconnectClient bean via autowire */ @Autowired private RhoconnectClient client; private static final String sourceName = "Contact"; // name of DAO model /* Call the notifyOnCreate method from RhoconnectClient bean to tell the backend of changes from RhoConnect server */ @Transactional public int addContact(Contact contact) { int id = contactDAO.addContact(contact); client.notifyOnCreate(sourceName, Integer.toString(id), contact); return id; } /* Call the notifyOnUpdate method from RhoconnectClient bean to tell the backend of changes from RhoConnect server */ @Transactional public void updateContact(Contact contact) { contactDAO.updateContact(contact); client.notifyOnUpdate(sourceName, Integer.toString(contact.getId()), contact); } /* Call the notifyOnDelete method from RhoconnectClient bean to tell the backend of changes from RhoConnect server */ @Transactional public void removeContact(Integer id) { contactDAO.removeContact(id); client.notifyOnDelete(sourceName, Integer.toString(id)); } @Transactional public List listContact() { return contactDAO.listContact(); } @Transactional public Contact getContact(Integer id) { return contactDAO.getContact(id); } /* Implement the rhoconnectQuery method to communicate query in backend to the RhoConnect server */ @Override @Transactional public Map rhoconnectQuery(String partition) { Map h = new HashMap(); List contacts = listContact(); Iterator it = contacts.iterator( ); while(it.hasNext()) { Contact c =(Contact)it.next(); h.put(c.getId().toString(), c); } return h; } /* Implement the rhoconnectCreate method to communicate create in backend to the RhoConnect server */ @Override @Transactional public Integer rhoconnectCreate(String partition, Map attributes) { Contact contact = new Contact(); try { BeanUtils.populate(contact, attributes); int id = addContact(contact); return id; } catch(Exception e) { e.printStackTrace(); } return null; } /* Implement the rhoconnectUpdate method to communicate updates in backend to the RhoConnect server */ @Override @Transactional public Integer rhoconnectUpdate(String partition, Map attributes) { Integer id = Integer.parseInt((String)attributes.get("id")); Contact contact = getContact(id); try { BeanUtils.populate(contact, attributes); updateContact(contact); return id; } catch(Exception e) { e.printStackTrace(); } return null; } /* Implement the rhoconnectDelete method to communicate delete in backend to the RhoConnect server */ @Override @Transactional public Integer rhoconnectDelete(String partition, Map attributes) { String objId = (String)attributes.get("id"); Integer id = Integer.parseInt(objId); removeContact(id); return id; } } Click [here](https://github.com/shurab/RhoconnectJavaPluginDemo) to download the full source code of a Contact manager application with rhoconnect-java plugin. ## Meta Created and maintained by Alexander Babichev. Released under the [MIT License](http://www.opensource.org/licenses/mit-license.php).