struts2-protobuf-plugin-demo-parent

Struts2 protobuf plubin demo parent

License

License

Categories

Categories

Protobuf Data Data Structures
GroupId

GroupId

com.github.junahan
ArtifactId

ArtifactId

struts2-protobuf-plugin-demo-parent
Last Version

Last Version

1.0.0
Release Date

Release Date

Type

Type

pom
Description

Description

struts2-protobuf-plugin-demo-parent
Struts2 protobuf plubin demo parent

Download struts2-protobuf-plugin-demo-parent

How to add to project

<!-- https://jarcasting.com/artifacts/com.github.junahan/struts2-protobuf-plugin-demo-parent/ -->
<dependency>
    <groupId>com.github.junahan</groupId>
    <artifactId>struts2-protobuf-plugin-demo-parent</artifactId>
    <version>1.0.0</version>
    <type>pom</type>
</dependency>
// https://jarcasting.com/artifacts/com.github.junahan/struts2-protobuf-plugin-demo-parent/
implementation 'com.github.junahan:struts2-protobuf-plugin-demo-parent:1.0.0'
// https://jarcasting.com/artifacts/com.github.junahan/struts2-protobuf-plugin-demo-parent/
implementation ("com.github.junahan:struts2-protobuf-plugin-demo-parent:1.0.0")
'com.github.junahan:struts2-protobuf-plugin-demo-parent:pom:1.0.0'
<dependency org="com.github.junahan" name="struts2-protobuf-plugin-demo-parent" rev="1.0.0">
  <artifact name="struts2-protobuf-plugin-demo-parent" type="pom" />
</dependency>
@Grapes(
@Grab(group='com.github.junahan', module='struts2-protobuf-plugin-demo-parent', version='1.0.0')
)
libraryDependencies += "com.github.junahan" % "struts2-protobuf-plugin-demo-parent" % "1.0.0"
[com.github.junahan/struts2-protobuf-plugin-demo-parent "1.0.0"]

Dependencies

test (2)

Group / Artifact Type Version
junit : junit jar 4.9
org.easymock : easymock jar 3.6

Project Modules

  • demo-model
  • demo-web
  • demo-client

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

  1. Protobuf Home, https://developers.google.com/protocol-buffers/.
  2. Struts2 Home, http://struts.apache.org.
  3. HttpClient Home, http://hc.apache.org/httpcomponents-client-ga/.
  4. Struts2 Protobuf Plugin Project, https://github.com/junahan/struts2-protobuf-plugin.

Versions

Version
1.0.0