README
1 Abstract
This project is designed for scenes as:
- Use Protobuf as internel communication protocol.
- Use Protobuf as exchange model to avoid to export persistent model (for example, JPA model) directly or used to replace the POJO mode interchange.
- Byside the RPC, we want to use protobuf over HTTP and are using Struts2 as web framework.
NOTE: README for Chinese version (中文版本) .
2 Features
- Utils support to populate protobuf message field to POJO object property and vice versa.
- Populate protobuf message field value to Action object property value automatically.
- Support protobuf message as result - including the succeed response, validation error (field/action error) or exceptions, all of them can be serialized as protobuf message.
3 Quick Start
The plugin-demo project implements a sample echo service as an example. You can access struts2-protobuf-plugin-demo to find more information.
3.1 The Structure of the Echo Service Demo
.
├── demo-client
│ └── src
│ └── main
│ ├── java
│ └── resources
├── demo-model
│ └── src
│ └── main
│ ├── java
│ └── proto
└── demo-web
└── src
└── main
├── java
├── resources
└── webapp
- demo-model define the protobuf message and will share between client and server.
- demo-web implements the echo service on server.
- demo-client is a echo command line client, it sends any echo message to server using HttpClient.
3.2 Define Demo Model
Demo mode defins protobuf message which can be used to generate Java code by using protoc tool. The model will be shared between clieng and server.
We suggest to define protobuf message XxxRequest and XxxResponse as top level message. Which can be used as a container to collect all other messages.
3.2.1 Echo Protobuf Message
The below code snippet defines the DemoRequest and DemoResponse message. In the demo project, both of them only have echo_message
field which is used to transfer the echo message.
syntax = "proto2";
package junahan.struts2.protobuf.demo;
option java_package="com.github.junahan.struts2.protobuf.demo";
option java_multiple_files = true;
option optimize_for = SPEED;
//import "junahan/struts2/protobuf/protocol.proto";
message DemoRequest {
optional string echo_message = 1;
// for extension
extensions 5000 to max;
}
message DemoResponse {
optional string echo_message = 1;
// for extension
extensions 5000 to max;
}
3.2.2 POM
To make it work, we need to add the protobuf-java
dependency and use protobuf-maven-plugin
to generate Java code from protobuf message definition.
<dependencies>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>${protobuf.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>${maven.protobuf.plugin.version}</version>
<configuration>
<protocExecutable>/usr/local/bin/protoc</protocExecutable>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
3.3 Server Code
The server code implements Echo service by EchoAction class and configure protobuf plugin stack for the Web service.
3.3.1 EchoAction Code
EchoAction implements the ProtobufResponseAware interface. Protobuf plubin interceptor only is performed on the action with this interface. The method execute
method handle the input echoMessage and build the DemoResponse message to return the echoMessage to client.
public class EchoAction extends ActionSupport implements ProtobufResponseAware {
private static final long serialVersionUID = -2144322110047021579L;
private String echoMessage;
private DemoResponse responseMessage;
@Override
public String execute() throws Exception {
if (echoMessage == null) echoMessage = " ";
DemoResponse.Builder drb = DemoResponse.newBuilder();
drb.setEchoMessage(echoMessage);
responseMessage = drb.build();
return Action.SUCCESS;
}
// ...
}
3.3.2 Add Dependencies to POM
EchoAction is dependency on struts2-protobuf-plugin and the demo-model:
<dependency>
<groupId>com.github.junahan</groupId>
<artifactId>struts2-protobuf-plugin-demo-model</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.github.junahan</groupId>
<artifactId>struts2-protobuf-plugin</artifactId>
<version>${project.version}</version>
</dependency>
3.3.3 Configure Struts Web
In the struts.xml, add the action configuration and the protobuf plubin interceptor stack configuration.
- User should configure the
protobuf.customFileDescriptorClasses
parameter to tell interceptor to load demo-model protobuf message file descriptor. - The result type of
echo
action should be type=”protobuf” which tell the system the action result should be a protobuf message.
<struts>
<package name="default" namespace="/" extends="protobuf-default">
<interceptors>
<interceptor-stack name="myDefaultStack">
<interceptor-ref name="protobufDefaultStack">
<param name="protobuf.customFileDescriptorClasses">
com.github.junahan.struts2.demo.protocol.DemoProtocol
</param>
</interceptor-ref>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="myDefaultStack"/>
<action name="echo" class="com.github.junahan.struts2.demo.actions.EchoAction">
<result type="protobuf"/>
</action>
</package>
</struts>
3.4 Client Code
Echo client is a commond line application which accept user’s typing from terminor and transfer it as ehco message to server by protobuf message. The echo web service will return the same message as response.
public static void main(String[] args) {
EchoClient client = new EchoClient();
@SuppressWarnings("resource")
Scanner scanner = new Scanner(System.in);
System.out.println("> Try any message and input '!q' to quit.");
while(true) {
System.out.print("> ");
String message = scanner.nextLine();
if (message.trim().equals("!q")) {
break;
}
try {
String echoMessage = client.doEcho(message);
System.out.println(echoMessage);
} catch (Exception e) {
System.out.println(e.getMessage());
LOG.debug(e);
}
}
// ...
}
3.5 Run the Example
- Run following command to build the demo:
cd plugin-demo
mvn clean package
- Run the web server:
cd demo-web
mvn:jetty:run
- Run the client
cd demo-client
target/struts2-protobuf-plugin-demo-client-1.0.0-SNAPSHOT.jar
- Typeing echo message in terminor
> Try any message and input '!q' to quit.
> Hello
Hello
>
4 TODO Develper Guide
4.1 Build from Source
- Clone the project from Github
git clone https://github.com/junahan/struts2-protobuf-plugin.git
- Build and Install
cd struts2-protobuf-plugin
mvn install
In this case, it will install a SNAPSHOT version in your local maven repository.
4.2 Run Embbded Jetty with demo-web
The project use maven jetty plugin to run the embbded jetty server for test purpose.
cd plugin-demo/demo-web
mvn jetty:run
5 Todo List
- Support to populate request message map type field to Action object property.
6 References
- Protobuf Home, https://developers.google.com/protocol-buffers/.
- Struts2 Home, http://struts.apache.org.
- HttpClient Home, http://hc.apache.org/httpcomponents-client-ga/.
- Struts2 Protobuf Plugin Project, https://github.com/junahan/struts2-protobuf-plugin.