Skip to content

Commit b26b6e1

Browse files
committed
Merge pull request #5 from neptulon/router
Add router/logger/echo middleware packages
2 parents 6f84482 + 629b6c4 commit b26b6e1

10 files changed

Lines changed: 141 additions & 68 deletions

File tree

build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ repositories {
1212
dependencies {
1313
compile fileTree(dir: 'libs', include: ['*.jar'])
1414
compile 'com.google.code.gson:gson:2.5'
15-
compile 'com.squareup.okhttp3:okhttp:3.0.0-RC1'
16-
compile 'com.squareup.okhttp3:okhttp-ws:3.0.0-RC1'
15+
compile 'com.squareup.okhttp3:okhttp:3.0.1'
16+
compile 'com.squareup.okhttp3:okhttp-ws:3.0.1'
1717
testCompile 'junit:junit:4.12'
1818
testCompile 'org.mockito:mockito-core:1.10.19'
1919
testCompile 'org.hamcrest:hamcrest-library:1.3'

neptulon-client.iml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@
1414
</content>
1515
<orderEntry type="inheritedJdk" />
1616
<orderEntry type="sourceFolder" forTests="false" />
17-
<orderEntry type="library" name="Gradle: com.google.code.gson:gson:2.5" level="project" />
18-
<orderEntry type="library" name="Gradle: com.squareup.okhttp3:okhttp:3.0.0-RC1" level="project" />
19-
<orderEntry type="library" name="Gradle: com.squareup.okhttp3:okhttp-ws:3.0.0-RC1" level="project" />
20-
<orderEntry type="library" name="Gradle: com.squareup.okio:okio:1.6.0" level="project" />
21-
<orderEntry type="library" scope="TEST" name="Gradle: junit:junit:4.12" level="project" />
2217
<orderEntry type="library" scope="TEST" name="Gradle: org.mockito:mockito-core:1.10.19" level="project" />
2318
<orderEntry type="library" scope="TEST" name="Gradle: org.hamcrest:hamcrest-library:1.3" level="project" />
2419
<orderEntry type="library" scope="TEST" name="Gradle: org.hamcrest:hamcrest-core:1.3" level="project" />
2520
<orderEntry type="library" scope="TEST" name="Gradle: org.objenesis:objenesis:2.1" level="project" />
21+
<orderEntry type="library" name="Gradle: com.google.code.gson:gson:2.5" level="project" />
22+
<orderEntry type="library" name="Gradle: com.squareup.okio:okio:1.6.0" level="project" />
23+
<orderEntry type="library" scope="TEST" name="Gradle: junit:junit:4.12" level="project" />
24+
<orderEntry type="library" name="Gradle: com.squareup.okhttp3:okhttp:3.0.1" level="project" />
25+
<orderEntry type="library" name="Gradle: com.squareup.okhttp3:okhttp-ws:3.0.1" level="project" />
2626
</component>
2727
<component name="org.twodividedbyzero.idea.findbugs">
2828
<option name="_basePreferences">

src/main/java/neptulon/client/ConnImpl.java

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,15 @@ public class ConnImpl implements Conn, WebSocketListener {
3030
private final OkHttpClient client;
3131
private final Request request;
3232
private final WebSocketCall wsCall;
33-
private final List<Middleware> middleware;
34-
private final Map<String, ResHandler> resHandlers;
33+
private final List<Middleware> middleware = new ArrayList<>();
34+
private final Map<String, ResHandler> resHandlers = new HashMap<>();
3535
private WebSocket ws;
3636
private boolean connected;
3737

3838
/**
3939
* Initializes a new connection with given server URL.
4040
*/
4141
public ConnImpl(String url) {
42-
middleware = new ArrayList<>();
43-
resHandlers = new HashMap<>();
44-
4542
client = new OkHttpClient.Builder()
4643
.connectTimeout(45, TimeUnit.SECONDS)
4744
.writeTimeout(300, TimeUnit.SECONDS)
@@ -63,18 +60,20 @@ public ConnImpl() {
6360
this("ws://10.0.2.2:3000");
6461
}
6562

66-
private void send(Object src) {
63+
void send(Object src) {
64+
String m = gson.toJson(src);
65+
logger.info("Outgoing message: " + m);
6766
try {
68-
ws.sendMessage(RequestBody.create(WebSocket.TEXT, gson.toJson(src)));
67+
ws.sendMessage(RequestBody.create(WebSocket.TEXT, m));
6968
} catch (IOException e) {
7069
e.printStackTrace();
7170
close();
7271
}
7372
}
7473

75-
/*
76-
* ######## Conn Implementation ########
77-
*/
74+
/***********************
75+
* Conn Implementation *
76+
***********************/
7877

7978
@Override
8079
public void useTLS(byte[] ca, byte[] clientCert, byte[] clientCertKey) {
@@ -98,14 +97,6 @@ public void middleware(Middleware mw) {
9897

9998
@Override
10099
public void connect() {
101-
// add sender middleware as the last middleware in stack
102-
middleware.add(new Middleware() {
103-
@Override
104-
public void handler(ReqCtx req) {
105-
send(req);
106-
}
107-
});
108-
109100
// enqueue this listener implementation to initiate the WebSocket connection
110101
wsCall.enqueue(this);
111102
}
@@ -143,9 +134,9 @@ public void close() {
143134
}
144135
}
145136

146-
/*
147-
* ######## WebSocketListener Implementation ########
148-
*/
137+
/************************************
138+
* WebSocketListener Implementation *
139+
************************************/
149140

150141
@Override
151142
public void onOpen(WebSocket webSocket, Response response) {
@@ -172,7 +163,7 @@ public void onMessage(ResponseBody message) throws IOException {
172163
}
173164

174165
// handle request message
175-
new ReqCtx(msg.id, msg.method, msg.params, middleware, gson).next();
166+
new ReqCtx(this, msg.id, msg.method, msg.params, middleware, gson).next();
176167
}
177168

178169
@Override

src/main/java/neptulon/client/Middleware.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44
* Middleware interface definition.
55
*/
66
public interface Middleware {
7-
void handler(ReqCtx req);
7+
void handler(ReqCtx ctx);
88
}
99

src/main/java/neptulon/client/ReqCtx.java

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@
44
import com.google.gson.JsonElement;
55

66
import java.util.List;
7+
import java.util.logging.Logger;
78

89
/**
910
* Request context.
1011
*/
1112
public class ReqCtx {
13+
private static final Logger logger = Logger.getLogger(ReqCtx.class.getSimpleName());
14+
private final ConnImpl conn;
1215
private final String id;
1316
private final String method;
1417
private final JsonElement params;
@@ -18,14 +21,27 @@ public class ReqCtx {
1821

1922
public Response response;
2023

21-
public ReqCtx(String id, String method, JsonElement params, List<Middleware> middleware, Gson gson) {
24+
public ReqCtx(ConnImpl conn, String id, String method, JsonElement params, List<Middleware> middleware, Gson gson) {
25+
this.conn = conn;
2226
this.id = id;
2327
this.method = method;
2428
this.params = params;
2529
this.middleware = middleware;
2630
this.gson = gson;
2731
}
2832

33+
public Conn getConn() {
34+
return conn;
35+
}
36+
37+
public String getID() {
38+
return id;
39+
}
40+
41+
public String getMethod() {
42+
return method;
43+
}
44+
2945
public <T> T getParams(Class<T> classOfT) {
3046
return gson.fromJson(params, classOfT);
3147
}
@@ -34,7 +50,15 @@ public void next() {
3450
mwIndex++;
3551

3652
if (mwIndex <= middleware.size()) {
37-
middleware.get(mwIndex-1).handler(this);
53+
middleware.get(mwIndex - 1).handler(this);
54+
return;
55+
}
56+
57+
if (response != null) {
58+
conn.send(response);
59+
return;
3860
}
61+
62+
logger.warning("No response provided for for request: " + getID() + ": " + getMethod());
3963
}
4064
}

src/main/java/neptulon/client/Response.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ public class Response<T> {
88
public final T result;
99
public final ResError error;
1010

11-
Response(String id, T result, ResError error) {
11+
public Response(String id, T result, ResError error) {
1212
this.id = id;
1313
this.result = result;
1414
this.error = error;
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package neptulon.client.middleware;
2+
3+
import neptulon.client.Middleware;
4+
import neptulon.client.ReqCtx;
5+
import neptulon.client.Response;
6+
7+
/**
8+
* Echoes request body as response.
9+
*/
10+
public class Echo implements Middleware {
11+
12+
@Override
13+
public void handler(ReqCtx ctx) {
14+
ctx.response = new Response<>(ctx.getID(), ctx.getParams(Object.class), null);
15+
}
16+
}
Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
11
package neptulon.client.middleware;
22

3+
import neptulon.client.Middleware;
4+
import neptulon.client.ReqCtx;
5+
36
/**
4-
* Neptulon request/response logger middleware.
7+
* Request/response logger middleware.
58
*/
6-
public class Logger {
9+
public class Logger implements Middleware {
10+
private static final java.util.logging.Logger logger = java.util.logging.Logger.getLogger(Logger.class.getSimpleName());
11+
12+
@Override
13+
public void handler(ReqCtx ctx) {
14+
logger.info(ctx.getParams(Object.class).toString());
15+
ctx.next();
16+
}
717
}
Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,31 @@
11
package neptulon.client.middleware;
22

3+
import neptulon.client.Middleware;
4+
import neptulon.client.ReqCtx;
5+
6+
import java.util.HashMap;
7+
import java.util.Map;
8+
39
/**
4-
* Neptulon router middleware.
10+
* Request router middleware.
511
*/
6-
public class Router {
12+
public class Router implements Middleware {
13+
private final Map<String, Middleware> routes = new HashMap<>();
14+
15+
/**
16+
* Adds a new request route registry.
17+
*/
18+
public void request(String route, Middleware mw) {
19+
routes.put(route, mw);
20+
}
21+
22+
@Override
23+
public void handler(ReqCtx ctx) {
24+
Middleware mw = routes.get(ctx.getMethod());
25+
if (mw != null) {
26+
mw.handler(ctx);
27+
}
28+
29+
ctx.next();
30+
}
731
}
Lines changed: 39 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,75 @@
11
package neptulon.client;
22

3+
import neptulon.client.middleware.Echo;
4+
import neptulon.client.middleware.Logger;
5+
import neptulon.client.middleware.Router;
36
import org.junit.Test;
47

8+
import java.util.concurrent.CountDownLatch;
9+
510
import static org.hamcrest.MatcherAssert.assertThat;
611
import static org.hamcrest.core.IsEqual.equalTo;
712

813
public class NeptulonTest {
9-
public static final String URL = "ws://127.0.0.1:3000";
14+
private static final String URL = "ws://127.0.0.1:3001";
1015

1116
@Test
12-
public void emailValidator_CorrectEmailSimple_ReturnsTrue() {
13-
assertThat("hazelnuts", 3, equalTo(3));
14-
}
15-
16-
@Test
17-
public void connect() {
17+
public void connect() throws InterruptedException {
1818
if (isTravis()) {
1919
return;
2020
}
2121

22-
class Test {
23-
final String message;
24-
25-
Test(String message) {
26-
this.message = message;
27-
}
28-
}
29-
3022
Conn conn = new ConnImpl(URL);
3123
conn.connect();
32-
33-
try {
34-
Thread.sleep(1000);
35-
} catch (InterruptedException e) {
36-
e.printStackTrace();
37-
}
38-
24+
Thread.sleep(100);
3925
assertThat("Connection was not established in time.", conn.isConnected());
4026

41-
// todo: add middleware to log the incoming message here and replace logger inside response handler with verifier
42-
// and release v0.1 corresponding to Neptulon v0.1
27+
conn.middleware(new Logger());
28+
Router router = new Router();
29+
router.request("echo", new Echo());
30+
conn.middleware(router);
31+
32+
final CountDownLatch counter = new CountDownLatch(2); // todo: add one more for ws.onClose
4333

44-
conn.middleware(new Middleware() {
34+
conn.sendRequest("echo", new EchoMessage("Hello from Java client!"), new ResHandler<Object>() {
4535
@Override
46-
public void handler(ReqCtx req) {
36+
public Class<Object> getType() {
37+
return Object.class;
38+
}
4739

40+
@Override
41+
public void handler(Response<Object> res) {
42+
System.out.println("Received 'echo' response: " + res.result);
43+
counter.countDown();
4844
}
4945
});
5046

51-
conn.sendRequest("test", new Test("wow"), new ResHandler<String>() {
47+
conn.sendRequest("close", new EchoMessage("Bye from Java client!"), new ResHandler<Object>() {
5248
@Override
53-
public Class<String> getType() {
54-
return String.class;
49+
public Class<Object> getType() {
50+
return Object.class;
5551
}
5652

5753
@Override
58-
public void handler(Response<String> res) {
59-
System.out.println("Received response: " + res.result);
54+
public void handler(Response<Object> res) {
55+
System.out.println("Received 'close' response: " + res.result);
56+
counter.countDown();
6057
}
6158
});
59+
60+
counter.await();
61+
conn.close();
6262
}
6363

6464
private boolean isTravis() {
6565
return System.getenv().containsKey("TRAVIS");
6666
}
67+
68+
private class EchoMessage {
69+
final String message;
70+
71+
EchoMessage(String message) {
72+
this.message = message;
73+
}
74+
}
6775
}

0 commit comments

Comments
 (0)