Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/shannah/cn1rpc
RPC library for Codename One
https://github.com/shannah/cn1rpc
Last synced: about 1 month ago
JSON representation
RPC library for Codename One
- Host: GitHub
- URL: https://github.com/shannah/cn1rpc
- Owner: shannah
- Created: 2015-07-06T23:23:30.000Z (over 9 years ago)
- Default Branch: master
- Last Pushed: 2016-11-03T16:22:54.000Z (about 8 years ago)
- Last Synced: 2023-04-01T05:43:20.402Z (over 1 year ago)
- Language: Java
- Size: 15.2 MB
- Stars: 1
- Watchers: 2
- Forks: 0
- Open Issues: 3
-
Metadata Files:
- Readme: README.adoc
Awesome Lists containing this project
README
= CN1RPC
A library to facilitate RPC between Codename One clients and Java servers== Synopsis
This library provides a minimal set of annotations to generate RPC client and server code for Codename One applications. The library itself meant to be used in Java server projects, but it includes a mechanism to seamlessly keep client projects in sync.
== Features
* **Seamless integration** between Codename One clients and Java web servers.
* **Uses Annotations to generate boiler-plate code**. All you write is the server API as plain Java methods, and your client can call them directly using RPC as if they were just regular client java methods.
* **Client and Server Always In Sync**. Because it uses annotations, all glue code is generated automatically on compile. If you change your API everything will be updated automatically.
* **Compatible with all Codename One Platforms**
* **IDE Agnostic**. Since it uses Annotations, it doesn't rely on any particular IDE or build tool. Should work with Ant, Gradle, Maven, Eclipse, Netbeans, IntelliJ, or just plain command-line Javac if that's your thing.
* **Support for POJO Parameters and Return Types**. Includes annotations to generate appropriate Codename One serialization. No need to implement `internalize()` and `externalize()` by hand. Just write your POJO class add the `@Externalizable` annotation, and it will be shared automatically with both client and server projects.
* **API Versioning Support**. Read more https://github.com/shannah/CN1RPC/wiki/Versioning-Externalizables[here].== Tutorials
* **https://github.com/shannah/CN1RPC/wiki/SimpleAdder-Tutorial[SimpleAdder Tutorial]** - An introductory tutorial for beginners on how to set up a very basic client-server application with CN1RPC
* **https://github.com/shannah/CN1RPC/wiki/Movie-Database-Tutorial[Movie Database Tutorial]** - Level 2 tutorial, showing a more complex application that involves passing POJOs as parameters and return types.== Installation
**Maven Projects**:
First clone this repo and install with Maven
----
$ git clone https://github.com/shannah/CN1RPC.git
$ cd CN1RPC/CodenameOneServerAnnotationsMaven
$ mvn install
----Next add dependencies to your Java server project.
Add the following to your pom.xml:
----
com.codename1
cn1rpc
0.1.0-SNAPSHOT----
**Non-Maven Projects**
* Download https://github.com/shannah/CN1RPC/raw/master/TestWebApp/lib/cn1rpc-0.1.0-SNAPSHOT.jar[CN1RPC]
* Download https://github.com/shannah/CN1RPC/raw/master/TestWebApp/lib/javapoet-1.2.0-SNAPSHOT.jar[JavaPoet] (Required by CN1RPC)Add them to your project's compile classpath.
== Usage
To create a web service that uses Codename One RPC, simply add the `@WebService` annotation to any class in your project. Then all `public` `static` methods in that class will be accessible to your Codename One client using RPC (remote procedure calls).
=== A simple example:
**Server-side Code**:
[source,java]
----
package com.example.myadder;import com.codename1.ws.annotations.WebService;
@WebService
public class TestWebServer {
public static int add(int a, int b) {
return a+b;
}
}
----**Client-side Code**:
[source,java]
----
package com.example.myapp;import com.example.myadder.TestWebServerProxy;
public class MyApp {
public void start() {
TestWebServerProxy proxy = new TestWebServerProxy("http://localhost:8080/myapp");
try {
int result = proxy.add(1,2); // should be 3
} catch (IOException ex) {
// deal with io error.
}
}
}
----This is *ALL* the code you need to write. Boiler-plate code is generated by Javac in the server project whenever it is compiled, and it is kept in sync so you don't have to worry about manually changing it later.
=== Example with Externalizable Classes
RPC methods can accept primitive types, strings, boxed types, arrays of primitive types, and arrays of strings. In addition it can accept objects custom classes that are marked with the `@Externalizable` annotation. All such classes are automatically shared by both the client and server projects. This allows you to pass arbitrarily complex objects back and forth between the client and server using RPC.
E.g.
**Server-side Code**:
[source,java]
----
package com.example.myadder;import com.codename1.ws.annotations.Externalizable;
@Externalizable
class CustomResponse {
int responseCode;
String message;
int additionResult;
// some accessors and getters here ...
}
----[source,java]
----
package com.example.myadder;import com.codename1.ws.annotations.WebService;
@WebService
public class TestWebServer {
public static CustomResponse add(int a, int b) {
int out = a+b;
// Use the ExternalizableFactory class (which is generated inside
// any package that includes @Externalizable classes to create
// instances of @Externalizable classes).
ExternalizableFactory f = new ExternalizableFactory();
CustomResponse response = f.create(CustomResponse.class);
response.setCode(200);
response.setMessage("Successfully added two numbers");
response.setAdditionResult(out);
return response;
}
}
----**Client-side Code**:
[source,java]
----
package com.example.myapp;import com.example.myadder.TestWebServerProxy;
public class MyApp {
public void start() {
TestWebServerProxy proxy = new TestWebServerProxy("http://localhost:8080/myapp");
try {
CustomResponse response = proxy.add(1,2);
response.getCode(); // 200
response.getMessage();
response.getAdditionResult(); // 3
} catch (IOException ex) {
// deal with io error.
}
}
}
----=== Synchronizing Server and Client Project Classes
The annotation processor handles the generation of all boiler-plate code for both the server and client. Generated client code is saved to a directory named `cn1-client-generated-sources` inside the server project's `build` directory (as a sibling directory of `generated-sources`).
You can automatically export the generated client source files to your client project using the `exports` attribute of the `@WebService` annotation. E.g.
[source,java]
----@WebService(exports={"/path/to/ClientProject"})
public class TestWebServer {
...
}
----You can also use a relative path (from the "source" directory of the server project).
[source,java]
----@WebService(exports={"../../../ClientProject"})
public class TestWebServer {
...
}
----=== Versioning
Eventually, you'll face the situation where the client is using older versions of Externalizable classes than the server. The server needs to be able to read old versions of classes, as well as write old versions so that it can still talk to old clients. See https://github.com/shannah/CN1RPC/wiki/Versioning-Externalizables[Versioning Executables] to learn how to handle this case.
== Demo Projects
See the https://github.com/shannah/CN1RPC-demos[CN1RPC-demos repository] for demo client-server projects using CN1RPC.
== Troubleshooting & Known Issues
=== 404 Error Trying to Access Servlet
When you try to run your Java Web Project in Netbeans by clicking the "Run" button, you are unable to access the servlet for your `@WebService` class, even though you are entering the correct URL. However if you perform a clean build then deploy the .war file to your servlet container, it works fine.
The reason is that there is a bug in Netbeans that causes code generation to break when "Compile on Save" is enabled.
==== Solution
Disable http://wiki.netbeans.org/FaqCompileOnSave[Compile on Save] and "Deploy on Save" in your project.