Author: jbarrez
Date: 2009-09-15 16:49:13 -0400 (Tue, 15 Sep 2009)
New Revision: 5645
Removed:
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/org/jbpm/trainticketdemo/message/
Modified:
projects/demos/trainticket-demo/jbpm-phone/trunk/pom.xml
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/LoadTest.java
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/org/jbpm/trainticketdemo/Demo.java
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/org/jbpm/trainticketdemo/gui/InboxPanel.java
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/org/jbpm/trainticketdemo/gui/PhonePanel.java
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/org/jbpm/trainticketdemo/gui/SendSmsPanel.java
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/org/jbpm/trainticketdemo/gui/fancy/AePlayWave.java
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/org/jbpm/trainticketdemo/http/HttpListener.java
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/org/jbpm/trainticketdemo/model/Inbox.java
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/org/jbpm/trainticketdemo/service/SmsService.java
Log:
Small enhancements to demo
Modified: projects/demos/trainticket-demo/jbpm-phone/trunk/pom.xml
===================================================================
--- projects/demos/trainticket-demo/jbpm-phone/trunk/pom.xml 2009-09-15 20:48:19 UTC (rev
5644)
+++ projects/demos/trainticket-demo/jbpm-phone/trunk/pom.xml 2009-09-15 20:49:13 UTC (rev
5645)
@@ -5,6 +5,16 @@
<artifactId>jBPM-Phone</artifactId>
<version>1.0</version>
+ <repositories>
+ <repository>
+ <id>repository.jboss.org</id>
+ <
url>http://repository.jboss.org/maven2</url>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </repository>
+ </repositories>
+
<dependencies>
<dependency>
<groupId>net.java.dev.timingframework</groupId>
@@ -16,6 +26,12 @@
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>
+ <dependency>
+ <groupId>org.jboss.netty</groupId>
+ <artifactId>netty</artifactId>
+ <version>3.1.2.GA</version>
+ </dependency>
+
</dependencies>
<build>
Modified: projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/LoadTest.java
===================================================================
---
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/LoadTest.java 2009-09-15
20:48:19 UTC (rev 5644)
+++
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/LoadTest.java 2009-09-15
20:49:13 UTC (rev 5645)
@@ -1,7 +1,4 @@
-import java.io.DataOutputStream;
import java.io.IOException;
-import java.net.ServerSocket;
-import java.net.Socket;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -12,6 +9,8 @@
import org.apache.commons.httpclient.methods.PostMethod;
import org.jbpm.trainticketdemo.http.HttpListener;
import org.jbpm.trainticketdemo.model.Inbox;
+import org.jbpm.trainticketdemo.model.SmsMessage;
+import org.jbpm.trainticketdemo.service.SmsService;
/*
* JBoss, Home of Professional Open Source
@@ -36,12 +35,17 @@
*/
/**
+ *
* @author Joram Barrez
*/
public class LoadTest {
-private static final String POST_URL =
"http://localhost:8080/jbpm-on-rails/receive_sms";
+ private static Inbox inbox;
+ private static CustomerAcceptanceThread customerThread;
+
+ private static final String POST_URL =
"http://localhost:8080/jbpm-on-rails/receive_sms";
+
private static final String PARAM_SEND_DATE = "sendDate";
private static final String PARAM_MSG_CONTENT = "msgContent";
@@ -53,26 +57,29 @@
public static void main(String[] args) throws Exception {
//Need http server for sms response
- Inbox inbox = new Inbox();
- HttpListener listener = new HttpListener(inbox);
- listener.start();
+ inbox = new Inbox();
+ new HttpListener(inbox);
+
+ customerThread = new CustomerAcceptanceThread();
+ customerThread.start();
+ int nrOfTicketRequests = 50;
+
+ final ExecutorService threadPool = Executors.newFixedThreadPool(25);
+
+
long start = System.currentTimeMillis();
- int max = 50;
-
- ExecutorService threadPool = Executors.newFixedThreadPool(5);
- //ArrayBlockingQueue<Runnable> queue = new
ArrayBlockingQueue<Runnable>(max);
- //ThreadPoolExecutor threadPool = new ThreadPoolExecutor(10,25,10, TimeUnit.SECONDS,
queue);
- for (int i=0; i < max; i++) {
+ for (int i=0; i < nrOfTicketRequests; i++) {
threadPool.execute(new Runnable() {
public void run() {
PostMethod post = new PostMethod(POST_URL);
post.addParameter(PARAM_SEND_DATE, new Date().toString());
post.addParameter(PARAM_MSG_CONTENT, "TICKET brussel antwerpen");
post.addParameter(PARAM_SENDER_NR, VALUE_SENDER_NR);
- HttpClient httpClient = new HttpClient();
+ final HttpClient httpClient = new HttpClient();
try {
httpClient.executeMethod(post);
+ post.releaseConnection();
} catch (HttpException e) {
e.printStackTrace();
} catch (IOException e) {
@@ -80,16 +87,90 @@
}
}
});
+
+ // After a while the OS can't close the sockets fast enough
+ // So we wait a bit for the OS to follow us
+ if (i % 50 == 0 ) {
+ Thread.sleep(5000);
+ }
+
}
// waits until all threads are executed
threadPool.shutdown();
- threadPool.awaitTermination(5, TimeUnit.HOURS);
+ threadPool.awaitTermination(1, TimeUnit.HOURS);
- long end = System.currentTimeMillis();
- System.out.println("TIME until all threads finished = " + (end-start));
+ System.out.println("TIME (ms) until all ticket requests have finished finished =
" + (System.currentTimeMillis()-start));
+
- //listener.stop();
+ while (inbox.getNrOfMessages() > customerThread.getNrOfProcessedMessages() + 1) {
+ System.out.println("All msgs not yet processed. Sleeping for 2.5s");
+ Thread.sleep(2500);
+ }
+ System.out.println("TIME (ms) until all acceptance msgs have been processed =
" + (System.currentTimeMillis()-start));
+
+ Thread.sleep(5000); // Let everything cool down
+ System.exit(0);
}
+ private static class CustomerAcceptanceThread extends Thread {
+
+ private int index = 0;
+
+ public int getNrOfProcessedMessages() {
+ return index;
+ }
+
+ public void run() {
+
+ // Wait until a few tasks are finished
+ try {
+ System.out.println("Customer acceptance thread sleeping for 5000ms ");
+ Thread.sleep(5000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ final ExecutorService acceptThreadPool = Executors.newFixedThreadPool(10);
+
+ while(true) {
+
+ while (inbox.getNrOfMessages() > index + 1) {
+
+ final String msg = getAcceptanceMessage();
+
+ if (msg != null) {
+
+ acceptThreadPool.execute(new Runnable() {
+
+ public void run() {
+ try {
+ SmsService.sendSms(msg);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ });
+
+ }
+
+ }
+ }
+ }
+
+ private String getAcceptanceMessage() {
+ SmsMessage msg = inbox.get(index++);
+ String content = msg.getContent();
+
+ // ACCEPT msg
+ int acceptIndexStart = content.indexOf("'");
+ if (acceptIndexStart > 0) {
+ int acceptIndexEnd = content.indexOf("'", acceptIndexStart + 1);
+ return content.substring(acceptIndexStart + 1, acceptIndexEnd);
+ }
+ return null;
+ }
+
+ }
+
}
Modified:
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/org/jbpm/trainticketdemo/Demo.java
===================================================================
---
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/org/jbpm/trainticketdemo/Demo.java 2009-09-15
20:48:19 UTC (rev 5644)
+++
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/org/jbpm/trainticketdemo/Demo.java 2009-09-15
20:49:13 UTC (rev 5645)
@@ -41,9 +41,8 @@
// Set up SMS inbox for cellphone
final Inbox inbox = new Inbox();
- // Set up Http Listener
+ // Set up Http Listener which will update inbox with incoming msgs
final HttpListener httpListener = new HttpListener(inbox);
- httpListener.start();
// Set up GUI
UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
Modified:
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/org/jbpm/trainticketdemo/gui/InboxPanel.java
===================================================================
---
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/org/jbpm/trainticketdemo/gui/InboxPanel.java 2009-09-15
20:48:19 UTC (rev 5644)
+++
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/org/jbpm/trainticketdemo/gui/InboxPanel.java 2009-09-15
20:49:13 UTC (rev 5645)
@@ -43,6 +43,8 @@
import org.jbpm.trainticketdemo.model.SmsMessage;
/**
+ * Screen showing the inbox of the cellphone
+ *
* @author Joram Barrez
*/
public class InboxPanel extends JPanel {
Modified:
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/org/jbpm/trainticketdemo/gui/PhonePanel.java
===================================================================
---
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/org/jbpm/trainticketdemo/gui/PhonePanel.java 2009-09-15
20:48:19 UTC (rev 5644)
+++
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/org/jbpm/trainticketdemo/gui/PhonePanel.java 2009-09-15
20:49:13 UTC (rev 5645)
@@ -41,6 +41,9 @@
import org.jbpm.trainticketdemo.model.Inbox;
/**
+ * General panel when the phone is started.
+ * Has buttons to to go to other screens.
+ *
* @author Joram Barrez
*/
public class PhonePanel extends JPanel implements MouseMotionListener, MouseListener,
ChangeListener {
Modified:
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/org/jbpm/trainticketdemo/gui/SendSmsPanel.java
===================================================================
---
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/org/jbpm/trainticketdemo/gui/SendSmsPanel.java 2009-09-15
20:48:19 UTC (rev 5644)
+++
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/org/jbpm/trainticketdemo/gui/SendSmsPanel.java 2009-09-15
20:49:13 UTC (rev 5645)
@@ -41,6 +41,8 @@
import org.jbpm.trainticketdemo.service.SmsService;
/**
+ * Screen used when sending a SMS.
+ *
* @author Joram Barrez
*/
public class SendSmsPanel extends JPanel {
Modified:
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/org/jbpm/trainticketdemo/gui/fancy/AePlayWave.java
===================================================================
---
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/org/jbpm/trainticketdemo/gui/fancy/AePlayWave.java 2009-09-15
20:48:19 UTC (rev 5644)
+++
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/org/jbpm/trainticketdemo/gui/fancy/AePlayWave.java 2009-09-15
20:49:13 UTC (rev 5645)
@@ -12,7 +12,7 @@
import javax.sound.sampled.UnsupportedAudioFileException;
/**
- * Borrowed from
http://www.anyexample.com/programming/java/java_play_wav_sound_file.xml
+ * Inspired by
http://www.anyexample.com/programming/java/java_play_wav_sound_file.xml
* @jbarrez (small adaptations)
*/
public class AePlayWave {
Modified:
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/org/jbpm/trainticketdemo/http/HttpListener.java
===================================================================
---
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/org/jbpm/trainticketdemo/http/HttpListener.java 2009-09-15
20:48:19 UTC (rev 5644)
+++
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/org/jbpm/trainticketdemo/http/HttpListener.java 2009-09-15
20:49:13 UTC (rev 5645)
@@ -21,98 +21,118 @@
*/
package org.jbpm.trainticketdemo.http;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.net.URLDecoder;
import java.util.concurrent.Executors;
+import org.jboss.netty.bootstrap.ServerBootstrap;
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.channel.ChannelFuture;
+import org.jboss.netty.channel.ChannelFutureListener;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.ChannelPipeline;
+import org.jboss.netty.channel.ChannelPipelineCoverage;
+import org.jboss.netty.channel.ChannelPipelineFactory;
+import org.jboss.netty.channel.Channels;
+import org.jboss.netty.channel.MessageEvent;
+import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
+import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
+import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
+import org.jboss.netty.handler.codec.http.HttpRequest;
+import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
+import org.jboss.netty.handler.codec.http.HttpResponse;
+import org.jboss.netty.handler.codec.http.HttpResponseEncoder;
+import org.jboss.netty.handler.codec.http.HttpResponseStatus;
+import org.jboss.netty.handler.codec.http.HttpVersion;
import org.jbpm.trainticketdemo.model.Inbox;
import org.jbpm.trainticketdemo.model.SmsMessage;
-import com.sun.net.httpserver.HttpExchange;
-import com.sun.net.httpserver.HttpHandler;
-import com.sun.net.httpserver.HttpServer;
-
/**
+ * Listens to incoming HTTP messages and forwards SMS messages to cellphone
+ * inbox when receiving a SMS through HTTP.
+ *
* @author Joram Barrez
*/
public class HttpListener {
-
+
+ private Inbox inbox;
+
public static final int HTTP_PORT = 4321;
-
+
public static final String URL = "/cellphone_sms_listener";
-
- private HttpServer server;
-
- private Inbox inbox;
-
+
public HttpListener(Inbox inbox) throws Exception {
this.inbox = inbox;
- InetSocketAddress address = new InetSocketAddress(HTTP_PORT);
- server = HttpServer.create(address, 0);
- server.createContext(URL, new SmsHandler());
- server.setExecutor(Executors.newCachedThreadPool());
+
+ ServerBootstrap bootstrap = new ServerBootstrap(
+ new NioServerSocketChannelFactory(Executors
+ .newCachedThreadPool(), Executors.newCachedThreadPool()));
+ bootstrap.setPipelineFactory(new HttpServerPipelineFactory());
+ bootstrap.bind(new InetSocketAddress(HTTP_PORT));
}
-
- public void start() {
- server.start();
+
+ private class HttpServerPipelineFactory implements ChannelPipelineFactory {
+
+ public ChannelPipeline getPipeline() throws Exception {
+ ChannelPipeline pipeline = Channels.pipeline();
+ pipeline.addLast("decoder", new HttpRequestDecoder());
+ pipeline.addLast("encoder", new HttpResponseEncoder());
+ pipeline.addLast("handler", new HttpRequestHandler());
+ return pipeline;
+ }
+
}
-
- public void stop() {
- server.stop(0);
- }
-
- private class SmsHandler implements HttpHandler {
- public void handle(HttpExchange httpExchange) throws IOException {
- if (httpExchange.getRequestMethod().equalsIgnoreCase("POST")) {
+ @ChannelPipelineCoverage("one")
+ private class HttpRequestHandler extends SimpleChannelUpstreamHandler {
+
+ @Override
+ public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
+ throws Exception {
+ final HttpRequest request = (HttpRequest) e.getMessage();
+
+ if (request.getUri().equalsIgnoreCase(URL)) {
+
+ // Get HTTP content
+ //ChannelBuffer contentBuffer = request.getContent();
+ String content = request.getContent().toString("UTF-8");
- // Read the raw content of the message
- StringBuilder strb = new StringBuilder();
- BufferedReader br = null;
- try {
- br = new BufferedReader(new InputStreamReader(httpExchange.getRequestBody()));
- String line = br.readLine();
- while (line != null) {
- strb.append(line);
- line = br.readLine();
- }
- } finally {
- if (br != null) {
- br.close();
- }
- }
- httpExchange.sendResponseHeaders(200, 0);
- httpExchange.close();
-
- // add the parsed message to the cellphone inbox
- SmsMessage smsMessage = parseRawMessage(strb.toString());
- inbox.addMessage(smsMessage);
+ // Send HTTP response
+ HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1,
HttpResponseStatus.OK);
+ ChannelFuture channelFuture = e.getChannel().write(response);
+ channelFuture.addListener(ChannelFutureListener.CLOSE);
+
+ // Decode SMS message and add to cellphone inbox
+ SmsMessage msg = parseRawMessage(content);
+ inbox.addMessage(msg);
+
+ } else {
+ System.err.println("Discarded msg for URI " + request.getUri());
}
+
}
-
- private SmsMessage parseRawMessage(String message) {
-
+
+ private SmsMessage parseRawMessage(String message) {
+
SmsMessage result = new SmsMessage();
-
+
String decoded = "";
try {
decoded = URLDecoder.decode(message, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
+
+ // parse string of form 'date=Tue+18+2009¶m2=1+a'
+ String[] splitOnParamChar = decoded.split("&");
- // parse string of form 'date=Tue+18+2009¶m2=1+a'
- String[] splitOnParamChar = decoded.split("&");
for (String s : splitOnParamChar) {
-
+
String[] splitOnKeyValue = s.split("=");
String key = splitOnKeyValue[0];
String value = splitOnKeyValue[1];
-
+
if (key.equalsIgnoreCase("sendDate")) {
result.setDate(value);
} else if (key.equalsIgnoreCase("msgContent")) {
@@ -120,12 +140,12 @@
} else if (key.equalsIgnoreCase("senderNr")) {
result.setSender(value);
}
-
+
}
-
+
return result;
}
-
+
}
}
Modified:
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/org/jbpm/trainticketdemo/model/Inbox.java
===================================================================
---
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/org/jbpm/trainticketdemo/model/Inbox.java 2009-09-15
20:48:19 UTC (rev 5644)
+++
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/org/jbpm/trainticketdemo/model/Inbox.java 2009-09-15
20:49:13 UTC (rev 5645)
@@ -30,6 +30,9 @@
import javax.swing.event.EventListenerList;
/**
+ * Class representing the inbox of a cellphone.
+ * In reality, nothing more than an arraylist of SmsMessages.
+ *
* @author Joram Barrez
*/
public class Inbox {
@@ -41,8 +44,17 @@
public Inbox() {
this.messages = new ArrayList<SmsMessage>();
}
+
+ public synchronized int getNrOfMessages() {
+ return messages.size();
+ }
+
+ // Doesn't need to be syncrhonized, since we're only adding
+ public SmsMessage get(int index) {
+ return messages.get(index);
+ }
- public void addMessage(SmsMessage smsMessage) {
+ public synchronized void addMessage(SmsMessage smsMessage) {
messages.add(smsMessage);
fireStateChanged();
}
Modified:
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/org/jbpm/trainticketdemo/service/SmsService.java
===================================================================
---
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/org/jbpm/trainticketdemo/service/SmsService.java 2009-09-15
20:48:19 UTC (rev 5644)
+++
projects/demos/trainticket-demo/jbpm-phone/trunk/src/main/java/org/jbpm/trainticketdemo/service/SmsService.java 2009-09-15
20:49:13 UTC (rev 5645)
@@ -28,6 +28,8 @@
import org.jbpm.trainticketdemo.http.HttpListener;
/**
+ * Service (or Util) to send an SMS to the server on localhost.
+ *
* @author Joram Barrez
*/
public class SmsService {