diff --git a/README.md b/README.md
index 31d9306..6510948 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,86 @@
# ALMI (Abstraction Layer for Multiserver Infrastructure)
+[](https://maven-badges.herokuapp.com/maven-central/com.matteobattilana/almi)
[](https://circleci.com/gh/MatteoBattilana/ALMI)
## Description
-ALMI is a JAVA multiserver framework for remote method calls management based on Netty and Jackson serialization, that adds an abstraction layer for multiserver communication.
+ALMI is a Java multiserver framework for remote method calls management based on Netty and Jackson serialization, that adds an abstraction layer for multiserver communication.
+
+This framework will semplify the cluster management, making methods accessibile from other server, that has ALMI running on a node in the cluster.
+
+## Setup
+Add ALMI dependencies in your pom.xml or eventually, go to the [Maven Repository](https://search.maven.org/artifact/com.matteobattilana/almi/0.1.0/jar) and download the jar library file.
+
+```xml
+
+ ...
+
+ com.matteobattilana
+ almi
+ 0.1.0
+
+
+```
+
+## Simple usage
+
+The following code will instantiate an ALMI server that is listening on the 8888 port (if not set, it will use the one described in the [Default configuration](#Default configuration) section).
+
+```java
+Almi server = AlmiBootstrap.bootstrap()
+ .withPort(8888)
+ .withRemoteCallTimeout(2000)
+ .withMethodsMapper(new MethodsMapper()
+ {
+ @Override
+ public void configure()
+ throws Exception
+ {
+ addMethods(
+ bindStatic(Calculator.class).method("execute", double.class, Calculator.Operation.class, double.class).withDefaultName(),
+ bind(new Calculator()).method(Calculator.class.getMethod("sqrt", double.class)).withName("positiveSqrt")
+ );
+ }
+ })
+ .start();
+```
+
+### MethodsMapper
+MethodsMapper will let you define the mapping beetwen the local method implementation and its remote name. This is used to make methods accessibile from other ALMI server, running on a node in the cluster.
+
+A MethodsMapper can be defined in-line as the one in previous example, or in a specific class. The `addMethods` will configure the methods passed as arguments, in order to expose them.
+```java
+public class MethodMapperImpl extends MethodsMapper
+{
+ private final ClientInformation mInstance1;
+
+ public MethodMapperImpl(
+ ClientInformation instance1
+ )
+ {
+ mInstance1 = instance1;
+ }
+
+ @Override
+ public void configure()
+ throws Exception
+ {
+ addMethods(
+ bind(mInstance1).method(ClientInformation.class.getMethod("helloWorld")).withDefaultName(),
+ bindStatic(ClientInformation.class).method(ClientInformation.class.getMethod("ping")).withDefaultName()
+ );
+ }
+}
+```
+
+
+## Configuration
+### Default configuration
+The defaul configuration loaded from static constants from the Constants.java:
+
+```java
+public static final int DEFAULT_PORT = 8888;
+public static final int DEFAULT_CONNECTION_TIMEOUT = 10000;
+public static final int DEFAULT_PROMISE_TIMEOUT = 10000;
+public static final String DEFAULT_THREAD_NAME = "almi-service";
+public static final String DEFAULT_ADDRESS = "localhost";
+```
diff --git a/examples/calculator/AlmiCalculator.java b/examples/calculator/AlmiCalculator.java
index 4b36570..a658714 100644
--- a/examples/calculator/AlmiCalculator.java
+++ b/examples/calculator/AlmiCalculator.java
@@ -2,7 +2,7 @@
import exceptions.InvisibleWrapperException;
import socket.Almi;
-import socket.bootstrap.DefaultAlmiBootstrap;
+import socket.bootstrap.AlmiBootstrap;
import socket.bootstrap.MethodsMapper;
import java.util.Arrays;
@@ -13,7 +13,7 @@ public class AlmiCalculator
public static void main(String[] args)
throws Exception
{
- Almi server = DefaultAlmiBootstrap.bootstrap()
+ Almi server = AlmiBootstrap.bootstrap()
.withPort(8888)
.withRemoteCallTimeout(2000)
.withMethodsMapper(new MethodsMapper()
diff --git a/examples/clientinformation/ClientInformation.java b/examples/clientinformation/ClientInformation.java
index 7db05dc..4abcfa8 100644
--- a/examples/clientinformation/ClientInformation.java
+++ b/examples/clientinformation/ClientInformation.java
@@ -1,7 +1,7 @@
package clientinformation;
import socket.Almi;
-import socket.bootstrap.DefaultAlmiBootstrap;
+import socket.bootstrap.AlmiBootstrap;
import socket.bootstrap.MethodsMapper;
import java.lang.management.ManagementFactory;
@@ -11,7 +11,7 @@ public class ClientInformation implements Methods
public static void main(String[] args)
throws Exception
{
- Almi server = DefaultAlmiBootstrap.bootstrap()
+ Almi server = AlmiBootstrap.bootstrap()
.withPort(8888)
.withThreadName("ClientInformation-ALMI-server")
.withRemoteCallTimeout(2000)
diff --git a/examples/pingpong/AlmiPingPong.java b/examples/pingpong/AlmiPingPong.java
new file mode 100644
index 0000000..21daf79
--- /dev/null
+++ b/examples/pingpong/AlmiPingPong.java
@@ -0,0 +1,33 @@
+package pingpong;
+
+import socket.Almi;
+import socket.bootstrap.AlmiBootstrap;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+public class AlmiPingPong
+{
+ public static void main(String[] args)
+ throws Exception
+ {
+ Almi server = AlmiBootstrap.bootstrap()
+ .withPort(8888)
+ .withRemoteCallTimeout(2000)
+ .withMethodsMapper(new MethodsMapperImpl(new PingPong()))
+ .start();
+
+ PingPong.State state = PingPong.State.PING;
+ for(int i = 0; i < 10; i++)
+ {
+ state = server.callMethod(
+ "localhost",
+ 8888,
+ "ping",
+ Collections.singletonList(state)
+ );
+ System.out.println(state);
+ }
+ server.stop();
+ }
+}
diff --git a/examples/pingpong/MethodsMapperImpl.java b/examples/pingpong/MethodsMapperImpl.java
new file mode 100644
index 0000000..75d147c
--- /dev/null
+++ b/examples/pingpong/MethodsMapperImpl.java
@@ -0,0 +1,22 @@
+package pingpong;
+
+import socket.bootstrap.MethodsMapper;
+
+public class MethodsMapperImpl extends MethodsMapper
+{
+ private final PingPong mPingPong;
+
+ public MethodsMapperImpl(PingPong pingPong)
+ {
+ mPingPong = pingPong;
+ }
+
+ @Override
+ public void configure()
+ throws Exception
+ {
+ addMethods(
+ bind(mPingPong).method("getReponse", PingPong.State.class).withName("ping")
+ );
+ }
+}
diff --git a/examples/pingpong/PingPong.java b/examples/pingpong/PingPong.java
new file mode 100644
index 0000000..2fc95a5
--- /dev/null
+++ b/examples/pingpong/PingPong.java
@@ -0,0 +1,37 @@
+package pingpong;
+
+public class PingPong
+{
+ public enum State
+ {
+ PING("ping"),
+ PONG("pong"),
+ UNKNOWN("");
+
+ private final String mState;
+
+ State(String state)
+ {
+ mState = state;
+ }
+
+ @Override
+ public String toString()
+ {
+ return mState;
+ }
+ }
+
+ public State getReponse(State request)
+ {
+ switch(request)
+ {
+ case PING:
+ return State.PONG;
+ case PONG:
+ return State.PING;
+ default:
+ return State.UNKNOWN;
+ }
+ }
+}
diff --git a/pom.xml b/pom.xml
index 4d2749a..6fee0df 100644
--- a/pom.xml
+++ b/pom.xml
@@ -8,8 +8,8 @@
UTF-8
com.matteobattilana
- com.matteobattilana
- 1.0-SNAPSHOT
+ almi
+ 0.1.1
@@ -19,7 +19,6 @@
false
-
org.apache.maven.plugins
maven-compiler-plugin
@@ -29,8 +28,101 @@
8
+
+ org.sonatype.plugins
+ nexus-staging-maven-plugin
+ 1.6.7
+ true
+
+ ossrh
+ https://oss.sonatype.org/
+ true
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 2.2.1
+
+
+ attach-sources
+
+ jar-no-fork
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 2.9.1
+
+
+ attach-javadocs
+
+ jar
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-gpg-plugin
+ 1.5
+
+
+ sign-artifacts
+ verify
+
+ sign
+
+
+
+
+ jar
+ ALMI (Abstraction Layer for Multiserver Infrastructure)
+ ALMI is a Java multiserver framework for remote method calls management based on Netty and Jackson serialization, that adds an abstraction layer for multiserver communication.
+ https://github.com/MatteoBattilana/ALMI
+
+
+ The Apache License, Version 2.0
+ http://www.apache.org/licenses/LICENSE-2.0.txt
+
+
+
+
+
+ release
+
+
+
+
+
+ ossrh
+ https://oss.sonatype.org/content/repositories/snapshots
+
+
+ ossrh
+ https://oss.sonatype.org/service/local/staging/deploy/maven2/
+
+
+
+
+ scm:git:git://github.com/MatteoBattilana/ALMI.git
+ scm:git:ssh://github.com/MatteoBattilana/ALMI.git
+ http://github.com/MatteoBattilana/ALMI/tree/master
+
+
+
+
+ Matteo Battilana
+ matteo@matteobattilana.com
+ http://matteobattilana.com
+ http://matteobattilana.com
+
+
diff --git a/src/main/java/socket/bootstrap/AlmiBootstrap.java b/src/main/java/socket/bootstrap/AlmiBootstrap.java
index 0752a51..eedbe49 100644
--- a/src/main/java/socket/bootstrap/AlmiBootstrap.java
+++ b/src/main/java/socket/bootstrap/AlmiBootstrap.java
@@ -1,57 +1,144 @@
package socket.bootstrap;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
import exceptions.AlmiException;
import exceptions.InvalidPropertiesFileException;
+import exceptions.MethodMapperException;
+import guice.AlmiModules;
+import method.MethodDescriptor;
import socket.Almi;
+import socket.AlmiFactory;
+import utils.Constants;
+import utils.PropertiesUtils;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
import java.util.Properties;
-public interface AlmiBootstrap
+public class AlmiBootstrap implements Bootstrap
{
- /**
- * @param name
- */
- AlmiBootstrap withThreadName(String name);
-
- /**
- * @param address
- */
- AlmiBootstrap withAddress(String address);
-
- /**
- * @param port
- */
- AlmiBootstrap withPort(int port);
-
- /**
- * @param timeout
- */
- AlmiBootstrap withConnectionTimeout(int timeout);
-
- /**
- * @param timeout
- */
- AlmiBootstrap withRemoteCallTimeout(int timeout);
-
- /**
- * @param props
- */
- AlmiBootstrap from(Properties props)
- throws AlmiException;
-
- /**
- * @param path
- */
- AlmiBootstrap fromPropertiesFile(String path)
- throws AlmiException;
-
- /**
- * @param mapper
- */
- AlmiBootstrap withMethodsMapper(MethodsMapper mapper)
- throws AlmiException;
-
- Almi start()
- throws AlmiException;
+ private final AlmiFactory mAlmiFactory;
+
+ private Map mMethodDescriptorMap = new HashMap<>();
+ private String mThreadName = Constants.DEFAULT_THREAD_NAME;
+ private String mSocketAddress = Constants.DEFAULT_ADDRESS;
+ private int mPort = Constants.DEFAULT_PORT;
+ private int mConnectTimeout = Constants.DEFAULT_CONNECTION_TIMEOUT;
+ private int mPromiseTimeout = Constants.DEFAULT_PROMISE_TIMEOUT;
+
+ public static AlmiBootstrap bootstrap()
+ {
+ Injector injector = Guice.createInjector(new AlmiModules());
+
+ return new AlmiBootstrap(
+ injector.getInstance(AlmiFactory.class)
+ );
+ }
+
+ private AlmiBootstrap(AlmiFactory almiFactory)
+ {
+ mAlmiFactory = almiFactory;
+ }
+
+ @Override
+ public Bootstrap from(Properties props) throws AlmiException
+ {
+ withThreadName(PropertiesUtils.optString(props, Constants.PROPERTY_THREAD_NAME, Constants.DEFAULT_THREAD_NAME));
+ withAddress(PropertiesUtils.optString(props, Constants.PROPERTY_ADDRESS, Constants.DEFAULT_ADDRESS));
+ withPort(PropertiesUtils.optInt(props, Constants.PROPERTY_PORT, Constants.DEFAULT_PORT));
+ withConnectionTimeout(PropertiesUtils.optInt(props, Constants.PROPERTY_CONNECTION_TIMEOUT, Constants.DEFAULT_CONNECTION_TIMEOUT));
+ withRemoteCallTimeout(PropertiesUtils.optInt(props, Constants.PROPERTY_PROMISE_TIMEOUT, Constants.DEFAULT_PROMISE_TIMEOUT));
+ return this;
+ }
+
+ @Override
+ public Bootstrap fromPropertiesFile(String path)
+ throws AlmiException
+ {
+ File propertiesFile = new File(path);
+ Properties props = new Properties();
+
+ try(InputStream is = new FileInputStream(propertiesFile))
+ {
+ props.load(is);
+ return from(props);
+ }
+ catch(IOException e)
+ {
+ throw new InvalidPropertiesFileException(path, e);
+ }
+ }
+
+ @Override
+ public Bootstrap withMethodsMapper(MethodsMapper mapper) throws AlmiException
+ {
+ try
+ {
+ mapper.configure();
+ mMethodDescriptorMap = mapper.methodDescriptorMap();
+ }
+ catch(Exception e)
+ {
+ throw new MethodMapperException(e);
+ }
+ return this;
+ }
+
+ @Override
+ public Bootstrap withThreadName(String name)
+ {
+ mThreadName = name;
+ return this;
+ }
+
+ @Override
+ public Bootstrap withAddress(String address)
+ {
+ mSocketAddress = address;
+ return this;
+ }
+
+ @Override
+ public Bootstrap withPort(int port)
+ {
+ mPort = port;
+ return this;
+ }
+
+ @Override
+ public Bootstrap withConnectionTimeout(int timeout)
+ {
+ mConnectTimeout = timeout;
+ return this;
+ }
+
+ @Override
+ public Bootstrap withRemoteCallTimeout(int timeout)
+ {
+ mPromiseTimeout = timeout;
+ return this;
+ }
+
+ @Override
+ public Almi start()
+ {
+ return build().start();
+ }
+
+ private Almi build()
+ {
+ return mAlmiFactory.create(
+ mMethodDescriptorMap,
+ mThreadName,
+ mSocketAddress,
+ mPort,
+ mConnectTimeout,
+ mPromiseTimeout
+ );
+ }
}
diff --git a/src/main/java/socket/bootstrap/Bootstrap.java b/src/main/java/socket/bootstrap/Bootstrap.java
new file mode 100644
index 0000000..a90cc50
--- /dev/null
+++ b/src/main/java/socket/bootstrap/Bootstrap.java
@@ -0,0 +1,55 @@
+package socket.bootstrap;
+
+import exceptions.AlmiException;
+import socket.Almi;
+
+import java.util.Properties;
+
+public interface Bootstrap
+{
+ /**
+ * @param name
+ */
+ Bootstrap withThreadName(String name);
+
+ /**
+ * @param address
+ */
+ Bootstrap withAddress(String address);
+
+ /**
+ * @param port
+ */
+ Bootstrap withPort(int port);
+
+ /**
+ * @param timeout
+ */
+ Bootstrap withConnectionTimeout(int timeout);
+
+ /**
+ * @param timeout
+ */
+ Bootstrap withRemoteCallTimeout(int timeout);
+
+ /**
+ * @param props
+ */
+ Bootstrap from(Properties props)
+ throws AlmiException;
+
+ /**
+ * @param path
+ */
+ Bootstrap fromPropertiesFile(String path)
+ throws AlmiException;
+
+ /**
+ * @param mapper
+ */
+ Bootstrap withMethodsMapper(MethodsMapper mapper)
+ throws AlmiException;
+
+ Almi start()
+ throws AlmiException;
+}
diff --git a/src/main/java/socket/bootstrap/DefaultAlmiBootstrap.java b/src/main/java/socket/bootstrap/DefaultAlmiBootstrap.java
deleted file mode 100644
index 055e7d6..0000000
--- a/src/main/java/socket/bootstrap/DefaultAlmiBootstrap.java
+++ /dev/null
@@ -1,144 +0,0 @@
-package socket.bootstrap;
-
-import com.google.inject.Guice;
-import com.google.inject.Injector;
-import exceptions.AlmiException;
-import exceptions.InvalidPropertiesFileException;
-import exceptions.MethodMapperException;
-import guice.AlmiModules;
-import method.MethodDescriptor;
-import socket.Almi;
-import socket.AlmiFactory;
-import utils.Constants;
-import utils.PropertiesUtils;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-
-public class DefaultAlmiBootstrap implements AlmiBootstrap
-{
- private final AlmiFactory mAlmiFactory;
-
- private Map mMethodDescriptorMap = new HashMap<>();
- private String mThreadName = Constants.DEFAULT_THREAD_NAME;
- private String mSocketAddress = Constants.DEFAULT_ADDRESS;
- private int mPort = Constants.DEFAULT_PORT;
- private int mConnectTimeout = Constants.DEFAULT_CONNECTION_TIMEOUT;
- private int mPromiseTimeout = Constants.DEFAULT_PROMISE_TIMEOUT;
-
- public static DefaultAlmiBootstrap bootstrap()
- {
- Injector injector = Guice.createInjector(new AlmiModules());
-
- return new DefaultAlmiBootstrap(
- injector.getInstance(AlmiFactory.class)
- );
- }
-
- private DefaultAlmiBootstrap(AlmiFactory almiFactory)
- {
- mAlmiFactory = almiFactory;
- }
-
- @Override
- public AlmiBootstrap from(Properties props) throws AlmiException
- {
- withThreadName(PropertiesUtils.optString(props, Constants.PROPERTY_THREAD_NAME, Constants.DEFAULT_THREAD_NAME));
- withAddress(PropertiesUtils.optString(props, Constants.PROPERTY_ADDRESS, Constants.DEFAULT_ADDRESS));
- withPort(PropertiesUtils.optInt(props, Constants.PROPERTY_PORT, Constants.DEFAULT_PORT));
- withConnectionTimeout(PropertiesUtils.optInt(props, Constants.PROPERTY_CONNECTION_TIMEOUT, Constants.DEFAULT_CONNECTION_TIMEOUT));
- withRemoteCallTimeout(PropertiesUtils.optInt(props, Constants.PROPERTY_PROMISE_TIMEOUT, Constants.DEFAULT_PROMISE_TIMEOUT));
- return this;
- }
-
- @Override
- public AlmiBootstrap fromPropertiesFile(String path)
- throws AlmiException
- {
- File propertiesFile = new File(path);
- Properties props = new Properties();
-
- try(InputStream is = new FileInputStream(propertiesFile))
- {
- props.load(is);
- return from(props);
- }
- catch(IOException e)
- {
- throw new InvalidPropertiesFileException(path, e);
- }
- }
-
- @Override
- public AlmiBootstrap withMethodsMapper(MethodsMapper mapper) throws AlmiException
- {
- try
- {
- mapper.configure();
- mMethodDescriptorMap = mapper.methodDescriptorMap();
- }
- catch(Exception e)
- {
- throw new MethodMapperException(e);
- }
- return this;
- }
-
- @Override
- public AlmiBootstrap withThreadName(String name)
- {
- mThreadName = name;
- return this;
- }
-
- @Override
- public AlmiBootstrap withAddress(String address)
- {
- mSocketAddress = address;
- return this;
- }
-
- @Override
- public AlmiBootstrap withPort(int port)
- {
- mPort = port;
- return this;
- }
-
- @Override
- public AlmiBootstrap withConnectionTimeout(int timeout)
- {
- mConnectTimeout = timeout;
- return this;
- }
-
- @Override
- public AlmiBootstrap withRemoteCallTimeout(int timeout)
- {
- mPromiseTimeout = timeout;
- return this;
- }
-
- @Override
- public Almi start()
- {
- return build().start();
- }
-
- private Almi build()
- {
- return mAlmiFactory.create(
- mMethodDescriptorMap,
- mThreadName,
- mSocketAddress,
- mPort,
- mConnectTimeout,
- mPromiseTimeout
- );
- }
-}
diff --git a/src/main/java/socket/handler/MessageInboundHandler.java b/src/main/java/socket/handler/MessageInboundHandler.java
index ab40ac0..722b08a 100644
--- a/src/main/java/socket/handler/MessageInboundHandler.java
+++ b/src/main/java/socket/handler/MessageInboundHandler.java
@@ -36,7 +36,6 @@ public MessageInboundHandler(
public void channelActive(ChannelHandlerContext ctx)
throws Exception
{
- System.out.println("Connected!");
super.channelActive(ctx);
}
@@ -45,7 +44,6 @@ protected void channelRead0(ChannelHandlerContext ctx, BaseMessage in)
{
try
{
- System.out.println("Received: " + in.getClass());
in.interpret(this, ctx);
}
catch(Exception e)
@@ -61,7 +59,6 @@ protected void channelRead0(ChannelHandlerContext ctx, BaseMessage in)
@Override
public void channelInactive(ChannelHandlerContext ctx)
{
- System.out.println("Closed connection!");
ctx.fireChannelInactive();
}
diff --git a/src/main/java/utils/Constants.java b/src/main/java/utils/Constants.java
index 2c12af0..26725d3 100644
--- a/src/main/java/utils/Constants.java
+++ b/src/main/java/utils/Constants.java
@@ -5,7 +5,7 @@ public class Constants
public static final int DEFAULT_PORT = 8888;
public static final int DEFAULT_CONNECTION_TIMEOUT = 10000;
public static final int DEFAULT_PROMISE_TIMEOUT = 10000;
- public static final String DEFAULT_THREAD_NAME = "socket-service";
+ public static final String DEFAULT_THREAD_NAME = "almi-service";
public static final String DEFAULT_ADDRESS = "localhost";
public static final String PROPERTY_THREAD_NAME = "thread_name";
diff --git a/src/test/java/it-test/ServerTest.java b/src/test/java/it-test/ServerTest.java
index 7d04e1f..7b4d9b7 100644
--- a/src/test/java/it-test/ServerTest.java
+++ b/src/test/java/it-test/ServerTest.java
@@ -2,7 +2,7 @@
import org.junit.Before;
import org.junit.Test;
import socket.Almi;
-import socket.bootstrap.DefaultAlmiBootstrap;
+import socket.bootstrap.AlmiBootstrap;
import socket.bootstrap.MethodsMapper;
import java.util.Collections;
@@ -18,12 +18,12 @@ public class ServerTest
@Before
public void setup() throws Exception
{
- mServer1 = DefaultAlmiBootstrap.bootstrap()
+ mServer1 = AlmiBootstrap.bootstrap()
.withPort(mPort1)
.withRemoteCallTimeout(2000)
.start();
- mServer2 = DefaultAlmiBootstrap.bootstrap()
+ mServer2 = AlmiBootstrap.bootstrap()
.withPort(mPort2)
.withRemoteCallTimeout(2000)
.withMethodsMapper(new MethodsMapper()