I have set-up MQTT subscription as shown here:
package com.mqttW.demo;
import java.text.SimpleDateFormat;
import java.util.*;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.json.*;
public class WSync implements MqttCallback {
private String BROKER_URL = "";
private String PROTOCOL = "tcp://";
private String PORT = "1883";
private String TOPIC_ROOT_UNCNF = "/P/uncnf/";
private String TOPIC_ROOT_CNF = "/P/cnf/";
private DbOperations dbo = new DbOperations();
public void setBrokerUrl() {
this.BROKER_URL = PROTOCOL + System.getenv("BROKER_DNS") + ":" + PORT;
}
public String getBrokerUrl() {
return this.BROKER_URL;
}
public void publishPayload(String wName, String txnType, String payload) {
String clientId = wName + "-PUB";
String broker = this.getBrokerUrl();
String topic = TOPIC_ROOT_UNCNF + txnType + "/" + wName;
try {
MqttClient w = new MqttClient(broker, clientId);
w.connect();
MqttMessage message = new MqttMessage(payload.getBytes());
message.setQos(2);
w.publish(topic, message);
w.disconnect();
} catch (MqttException e) {
e.printStackTrace();
}
}
public void processTxns(String wName) {
this.setBrokerUrl();
String broker = this.getBrokerUrl();
String clientId = wName + "-SUB";
String topic = TOPIC_ROOT_CNF + wName + "/CR";
MemoryPersistence persistence = new MemoryPersistence();
try {
MqttConnectOptions c = new MqttConnectOptions();
c.setCleanSession(false);
MqttClient w = new MqttClient(broker, clientId, persistence);
w.connect(c);
w.setCallback(this);
w.subscribe(topic, 2);
System.out.println(w.getServerURI() + " " + w.getClientId() + " " + w.isConnected());
} catch (MqttException e) {
e.printStackTrace();
}
}
#Override
public void connectionLost(Throwable arg0) {
System.out.println("Connection lost at : " + new SimpleDateFormat("yyyy-MM-dd.HH:mm:ss").format(new java.util.Date()));
}
#Override
public void deliveryComplete(IMqttDeliveryToken arg0) {
// TODO Auto-generated method stub
}
#Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
String s = new String(message.getPayload());
System.out.println(s);
}
}
The class with this method does implement MqttCallback. The System.out.println shows the broker URL, client ID and connected status (true) correctly.
So, what I am not getting is, why does the code terminate? Why is the subscription not set-up to listen for messages?
I've successfully implemented the simple Java Amazon SWF example called hello_sample. I created the ActivityWorker executable that polls SWF for activity tasks to process. I created the WorkflowWorker executable that polls SWF for decision tasks and I have a WorkflowStarter executable that kicks off the workflow execution. It works as advertised. What I don't understand is how do I configure and add a second activity to run after the first activity?
WorkflowWorker:
public class WorkflowWorker {
private static final AmazonSimpleWorkflow swf = AmazonSimpleWorkflowClientBuilder.defaultClient();
public static void main(String[] args) {
PollForDecisionTaskRequest task_request =
new PollForDecisionTaskRequest()
.withDomain(Constants.DOMAIN)
.withTaskList(new TaskList().withName(Constants.TASKLIST));
while (true) {
System.out.println(
"WorkflowWorker is polling for a decision task from the tasklist '" +
Constants.TASKLIST + "' in the domain '" +
Constants.DOMAIN + "'.");
DecisionTask task = swf.pollForDecisionTask(task_request);
String taskToken = task.getTaskToken();
if (taskToken != null) {
try {
executeDecisionTask(taskToken, task.getEvents());
}
catch (Throwable th) {
th.printStackTrace();
}
}
}
}
private static void executeDecisionTask(String taskToken, List<HistoryEvent> events) throws Throwable {
List<Decision> decisions = new ArrayList<Decision>();
String workflow_input = null;
int scheduled_activities = 0;
int open_activities = 0;
boolean activity_completed = false;
String result = null;
System.out.println("WorkflowWorker is executing the decision task for the history events: [");
for (HistoryEvent event : events) {
System.out.println(" " + event);
switch(event.getEventType()) {
case "WorkflowExecutionStarted":
workflow_input = event.getWorkflowExecutionStartedEventAttributes().getInput();
break;
case "ActivityTaskScheduled":
scheduled_activities++;
break;
case "ScheduleActivityTaskFailed":
scheduled_activities--;
break;
case "ActivityTaskStarted":
scheduled_activities--;
open_activities++;
break;
case "ActivityTaskCompleted":
open_activities--;
activity_completed = true;
result = event.getActivityTaskCompletedEventAttributes().getResult();
break;
case "ActivityTaskFailed":
open_activities--;
break;
case "ActivityTaskTimedOut":
open_activities--;
break;
}
}
System.out.println("]");
if (activity_completed) {
decisions.add(
new Decision()
.withDecisionType(DecisionType.CompleteWorkflowExecution)
.withCompleteWorkflowExecutionDecisionAttributes(
new CompleteWorkflowExecutionDecisionAttributes()
.withResult(result)));
}
else {
if (open_activities == 0 && scheduled_activities == 0) {
ScheduleActivityTaskDecisionAttributes attrs =
new ScheduleActivityTaskDecisionAttributes()
.withActivityType(new ActivityType()
.withName(Constants.ACTIVITY)
.withVersion(Constants.ACTIVITY_VERSION))
.withActivityId(UUID.randomUUID().toString())
.withInput(workflow_input);
decisions.add(
new Decision()
.withDecisionType(DecisionType.ScheduleActivityTask)
.withScheduleActivityTaskDecisionAttributes(attrs));
}
else {
// an instance of HelloActivity is already scheduled or running. Do nothing, another
// task will be scheduled once the activity completes, fails or times out
}
}
System.out.println("WorkflowWorker is exiting the decision task with the decisions " + decisions);
swf.respondDecisionTaskCompleted(
new RespondDecisionTaskCompletedRequest()
.withTaskToken(taskToken)
.withDecisions(decisions));
}
}
ActivityWorker:
public class ActivityWorker {
private static final AmazonSimpleWorkflow swf = AmazonSimpleWorkflowClientBuilder.defaultClient();
private static CountDownLatch waitForTermination = new CountDownLatch(1);
private static volatile boolean terminate = false;
private static String executeActivityTask(String g_species) throws Throwable {
String s = " ******** Hello, " + g_species + "!";
System.out.println(s);
String cwd = Paths.get(".").toAbsolutePath().normalize().toString();
String filename = "g_species.txt";
Path filePath = Paths.get(cwd, filename);
String filePathName = filePath.toString();
BufferedWriter output = null;
try {
File file = new File (filePathName);
output = new BufferedWriter(new FileWriter(file));
output.write(g_species);
}
catch (IOException e) {
e.printStackTrace();
}
finally {
if (output != null) {
output.close();
}
}
return g_species;
}
public static void main(String[] args) {
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
try {
terminate = true;
System.out.println("ActivityWorker is waiting for the current poll request to return before shutting down.");
waitForTermination.await(60, TimeUnit.SECONDS);
}
catch (InterruptedException e) {
// ignore
System.out.println(e.getMessage());
}
}
});
try {
pollAndExecute();
}
finally {
waitForTermination.countDown();
}
}
public static void pollAndExecute() {
while (!terminate) {
System.out.println("ActivityWorker is polling for an activity task from the tasklist '"
+ Constants.TASKLIST + "' in the domain '" + Constants.DOMAIN + "'.");
ActivityTask task = swf.pollForActivityTask(new PollForActivityTaskRequest()
.withDomain(Constants.DOMAIN)
.withTaskList(new TaskList().withName(Constants.TASKLIST)));
String taskToken = task.getTaskToken();
if (taskToken != null) {
String result = null;
Throwable error = null;
try {
System.out.println("ActivityWorker is executing the activity task with input '" + task.getInput() + "'.");
result = executeActivityTask(task.getInput());
}
catch (Throwable th) {
error = th;
}
if (error == null) {
System.out.println("The activity task succeeded with result '" + result + "'.");
swf.respondActivityTaskCompleted(
new RespondActivityTaskCompletedRequest()
.withTaskToken(taskToken)
.withResult(result));
}
else {
System.out.println("The activity task failed with the error '"
+ error.getClass().getSimpleName() + "'.");
swf.respondActivityTaskFailed(
new RespondActivityTaskFailedRequest()
.withTaskToken(taskToken)
.withReason(error.getClass().getSimpleName())
.withDetails(error.getMessage()));
}
}
}
}
}
WorkflowStarter that kicks it all off:
public class WorkflowStarter {
private static final AmazonSimpleWorkflow swf = AmazonSimpleWorkflowClientBuilder.defaultClient();
public static final String WORKFLOW_EXECUTION = "HelloWorldWorkflowExecution";
public static void main(String[] args) {
String workflow_input = "Amazon SWF";
if (args.length > 0) {
workflow_input = args[0];
}
System.out.println("Starting the workflow execution '" + WORKFLOW_EXECUTION +
"' with input '" + workflow_input + "'.");
WorkflowType wf_type = new WorkflowType()
.withName(Constants.WORKFLOW)
.withVersion(Constants.WORKFLOW_VERSION);
Run run = swf.startWorkflowExecution(new StartWorkflowExecutionRequest()
.withDomain(Constants.DOMAIN)
.withWorkflowType(wf_type)
.withWorkflowId(WORKFLOW_EXECUTION)
.withInput(workflow_input)
.withExecutionStartToCloseTimeout("90"));
System.out.println("Workflow execution started with the run id '" +
run.getRunId() + "'.");
}
}
I would recommend to not reinvent the wheel and use the AWS Flow Framework for Java that is officially supported by Amazon. It already implements all the low level details and allows you to focus on a business logic of your workflow directly.
Here is an example worklow that uses three activities (taken from the developer guide).
Activities interface:
import com.amazonaws.services.simpleworkflow.flow.annotations.Activities;
import com.amazonaws.services.simpleworkflow.flow.annotations.ActivityRegistrationOptions;
#ActivityRegistrationOptions(defaultTaskScheduleToStartTimeoutSeconds = 300,
defaultTaskStartToCloseTimeoutSeconds = 10)
#Activities(version="1.0")
public interface GreeterActivities {
public String getName();
public String getGreeting(String name);
public void say(String what);
}
Activities implementation:
public class GreeterActivitiesImpl implements GreeterActivities {
#Override
public String getName() {
return "World";
}
#Override
public String getGreeting(String name) {
return "Hello " + name;
}
#Override
public void say(String what) {
System.out.println(what);
}
}
Workflow interface:
import com.amazonaws.services.simpleworkflow.flow.annotations.Execute;
import com.amazonaws.services.simpleworkflow.flow.annotations.Workflow;
import com.amazonaws.services.simpleworkflow.flow.annotations.WorkflowRegistrationOptions;
#Workflow
#WorkflowRegistrationOptions(defaultExecutionStartToCloseTimeoutSeconds = 3600)
public interface GreeterWorkflow {
#Execute(version = "1.0")
public void greet();
}
Workflow implementation:
import com.amazonaws.services.simpleworkflow.flow.core.Promise;
public class GreeterWorkflowImpl implements GreeterWorkflow {
private GreeterActivitiesClient operations = new GreeterActivitiesClientImpl();
public void greet() {
Promise<String> name = operations.getName();
Promise<String> greeting = operations.getGreeting(name);
operations.say(greeting);
}
}
The worker that hosts both of them. Obviously it can be broken into separate activity and workflow workers:
import com.amazonaws.ClientConfiguration;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflow;
import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflowClient;
import com.amazonaws.services.simpleworkflow.flow.ActivityWorker;
import com.amazonaws.services.simpleworkflow.flow.WorkflowWorker;
public class GreeterWorker {
public static void main(String[] args) throws Exception {
ClientConfiguration config = new ClientConfiguration().withSocketTimeout(70*1000);
String swfAccessId = System.getenv("AWS_ACCESS_KEY_ID");
String swfSecretKey = System.getenv("AWS_SECRET_KEY");
AWSCredentials awsCredentials = new BasicAWSCredentials(swfAccessId, swfSecretKey);
AmazonSimpleWorkflow service = new AmazonSimpleWorkflowClient(awsCredentials, config);
service.setEndpoint("https://swf.us-east-1.amazonaws.com");
String domain = "helloWorldWalkthrough";
String taskListToPoll = "HelloWorldList";
ActivityWorker aw = new ActivityWorker(service, domain, taskListToPoll);
aw.addActivitiesImplementation(new GreeterActivitiesImpl());
aw.start();
WorkflowWorker wfw = new WorkflowWorker(service, domain, taskListToPoll);
wfw.addWorkflowImplementationType(GreeterWorkflowImpl.class);
wfw.start();
}
}
The workflow starter:
import com.amazonaws.ClientConfiguration;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflow;
import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflowClient;
public class GreeterMain {
public static void main(String[] args) throws Exception {
ClientConfiguration config = new ClientConfiguration().withSocketTimeout(70*1000);
String swfAccessId = System.getenv("AWS_ACCESS_KEY_ID");
String swfSecretKey = System.getenv("AWS_SECRET_KEY");
AWSCredentials awsCredentials = new BasicAWSCredentials(swfAccessId, swfSecretKey);
AmazonSimpleWorkflow service = new AmazonSimpleWorkflowClient(awsCredentials, config);
service.setEndpoint("https://swf.us-east-1.amazonaws.com");
String domain = "helloWorldWalkthrough";
GreeterWorkflowClientExternalFactory factory = new GreeterWorkflowClientExternalFactoryImpl(service, domain);
GreeterWorkflowClientExternal greeter = factory.getClient("someID");
greeter.greet();
}
}
I need to parse the below JSON content. Currently I have stored it inflat file and reading it. I have given the sample POJO classes which are created and the code which I tried below.
Tried two different approach and both are giving the following error
Exception in thread "main" com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 3 path $
Json file
{
"DeviceCommon": {
"ASIdentifier": "123",
"DatadeliveyMechanism": "notify",
"MobileOriginatorCallbackReference": {
"url": "http://application.example.com/inbound/notifications/modatanotification/"
},
"AccessiblityCallbackReference": {
"url": "http://application.example.com/inbound/notifications/accessibilitystatusnotification"
}
},
"DeviceList": [{
"ExternalIdentifer": "123456#mydomain.com",
"msisdn": "123456",
"senderName": "Device1",
"MobileOriginatorCallbackReference": {
"notifyURL": "http://application.example.com/inbound/notifications/modatanotification/"
},
"ConfigurationResultCallbackReference": {
"notifyURL": "http://application.example.com/inbound/notifications/configurationResult"
},
"ASreferenceID": "AS000001",
"NIDDduration": "1d"
}]
}
POJO classes:
Note: I have mentioned only two classes here.
package com.As.jsonmodel.configrequest;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
#JsonIgnoreProperties(ignoreUnknown = true)
public class ConfigurationRequest
{
private DeviceList[] DeviceList;
private DeviceCommon DeviceCommon;
public DeviceList[] getDeviceList ()
{
return DeviceList;
}
public void setDeviceList (DeviceList[] DeviceList)
{
this.DeviceList = DeviceList;
}
public DeviceCommon getDeviceCommon ()
{
return DeviceCommon;
}
public void setDeviceCommon (DeviceCommon DeviceCommon)
{
this.DeviceCommon = DeviceCommon;
}
#Override
public String toString()
{
return "ClassPojo [DeviceList = "+DeviceList+", DeviceCommon = "+DeviceCommon+"]";
}
}
package com.As.jsonmodel.configrequest;
public class DeviceList
{
private MobileOriginatorCallbackReference MobileOriginatorCallbackReference;
private String NIDDduration;
private String ASreferenceID;
private String senderName;
private String ExternalIdentifer;
private String msisdn;
private ConfigurationResultCallbackReference ConfigurationResultCallbackReference;
public MobileOriginatorCallbackReference getMobileOriginatorCallbackReference ()
{
return MobileOriginatorCallbackReference;
}
public void setMobileOriginatorCallbackReference (MobileOriginatorCallbackReference MobileOriginatorCallbackReference)
{
this.MobileOriginatorCallbackReference = MobileOriginatorCallbackReference;
}
public String getNIDDduration ()
{
return NIDDduration;
}
public void setNIDDduration (String NIDDduration)
{
this.NIDDduration = NIDDduration;
}
public String getASreferenceID ()
{
return ASreferenceID;
}
public void setASreferenceID (String ASreferenceID)
{
this.ASreferenceID = ASreferenceID;
}
public String getSenderName ()
{
return senderName;
}
public void setSenderName (String senderName)
{
this.senderName = senderName;
}
public String getExternalIdentifer ()
{
return ExternalIdentifer;
}
public void setExternalIdentifer (String ExternalIdentifer)
{
this.ExternalIdentifer = ExternalIdentifer;
}
public String getMsisdn ()
{
return msisdn;
}
public void setMsisdn (String msisdn)
{
this.msisdn = msisdn;
}
public ConfigurationResultCallbackReference getConfigurationResultCallbackReference ()
{
return ConfigurationResultCallbackReference;
}
public void setConfigurationResultCallbackReference (ConfigurationResultCallbackReference ConfigurationResultCallbackReference)
{
this.ConfigurationResultCallbackReference = ConfigurationResultCallbackReference;
}
#Override
public String toString()
{
return "ClassPojo [MobileOriginatorCallbackReference = "+MobileOriginatorCallbackReference+", NIDD duration = "+NIDDduration+", AS referenceID = "+ASreferenceID+", senderName = "+senderName+", ExternalIdentifer = "+ExternalIdentifer+", msisdn = "+msisdn+", ConfigurationResultCallbackReference = "+ConfigurationResultCallbackReference+"]";
}
}
Json Reader
Approach1:
BufferedReader br = null;
try {
br = new BufferedReader(
new FileReader("/home/raj/apache-tomcat-8.0.3/webapps/file.json"));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
JsonReader jsonReader = new JsonReader(new FileReader("/home/raj/apache-tomcat-8.0.3/webapps/file.json"));
jsonReader.beginObject();
while (jsonReader.hasNext()) {
String name = jsonReader.nextName();
if (name.equals("DeviceCommon")) {
readApp(jsonReader);
}
}
jsonReader.endObject();
jsonReader.close();
}
public static void readApp(JsonReader jsonReader) throws IOException{
jsonReader.beginObject();
while (jsonReader.hasNext()) {
String name = jsonReader.nextName();
System.out.println(name);
if (name.contains("ASIdentifier")){
jsonReader.beginObject();
while (jsonReader.hasNext()) {
String n = jsonReader.nextName();
if (n.equals("MobileOriginatorCallbackReference")){
System.out.println(jsonReader.nextString());
}
if (n.equals("AccessiblityCallbackReference")){
System.out.println(jsonReader.nextInt());
}
if (n.equals("DeviceList")){
jsonReader.beginArray();
while (jsonReader.hasNext()) {
System.out.println(jsonReader.nextString());
}
jsonReader.endArray();
}
}
jsonReader.endObject();
}
}
jsonReader.endObject();
}
// TODO Auto-generated method stub
Aproach2:
Gson gson = new Gson();
DeviceList [] myTypes = gson.fromJson(new FileReader("/home/raj/apache-tomcat-8.0.3/webapps/file.json"), DeviceList[].class);
System.out.println(gson.toJson(myTypes));
Any pointers on how to parse this file will be helpful.
Here's how to do it with Gson:
import java.io.FileReader;
import java.util.Arrays;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
public class Main {
public static void main(String[] args) throws Exception {
Data data = new Gson().fromJson(new FileReader("data.json"), Data.class);
System.out.println(data);
}
}
class Data {
#SerializedName("DeviceCommon")
DeviceCommon deviceCommon;
#SerializedName("DeviceList")
DeviceListEntry[] deviceList;
#Override
public String toString() {
return "Data{" +
"\n deviceCommon=" + deviceCommon +
"\n deviceList=" + Arrays.toString(deviceList) +
"\n}";
}
}
class DeviceCommon {
#SerializedName("ASIdentifier")
String asIdentifier;
#SerializedName("DatadeliveyMechanism")
String datadeliveyMechanism;
#SerializedName("MobileOriginatorCallbackReference")
Url mobileOriginatorCallbackReference;
#SerializedName("AccessiblityCallbackReference")
Url accessiblityCallbackReference;
#Override
public String toString() {
return "DeviceCommon{" +
"\n asIdentifier='" + asIdentifier + '\'' +
"\n datadeliveyMechanism='" + datadeliveyMechanism + '\'' +
"\n mobileOriginatorCallbackReference=" + mobileOriginatorCallbackReference +
"\n accessiblityCallbackReference=" + accessiblityCallbackReference +
"\n }";
}
}
class DeviceListEntry {
#SerializedName("ExternalIdentifer")
String externalIdentifer;
String msisdn;
String senderName;
#SerializedName("MobileOriginatorCallbackReference")
NotifyUrl mobileOriginatorCallbackReference;
#SerializedName("ConfigurationResultCallbackReference")
NotifyUrl configurationResultCallbackReference;
#SerializedName("ASreferenceID")
String asReferenceID;
#SerializedName("NIDDduration")
String nidDduration;
#Override
public String toString() {
return "DeviceListEntry{" +
"\n externalIdentifer='" + externalIdentifer + '\'' +
"\n msisdn='" + msisdn + '\'' +
"\n senderName='" + senderName + '\'' +
"\n mobileOriginatorCallbackReference=" + mobileOriginatorCallbackReference +
"\n configurationResultCallbackReference=" + configurationResultCallbackReference +
"\n asReferenceID='" + asReferenceID + '\'' +
"\n nidDduration='" + nidDduration + '\'' +
"\n }";
}
}
class Url {
String url;
#Override
public String toString() {
return url;
}
}
class NotifyUrl {
String notifyURL;
#Override
public String toString() {
return notifyURL;
}
}
Running Main will result in the following output:
Data{
deviceCommon=DeviceCommon{
asIdentifier='123'
datadeliveyMechanism='notify'
mobileOriginatorCallbackReference=http://application.example.com/inbound/notifications/modatanotification/
accessiblityCallbackReference=http://application.example.com/inbound/notifications/accessibilitystatusnotification
}
deviceList=[DeviceListEntry{
externalIdentifer='123456#mydomain.com'
msisdn='123456'
senderName='Device1'
mobileOriginatorCallbackReference=http://application.example.com/inbound/notifications/modatanotification/
configurationResultCallbackReference=http://application.example.com/inbound/notifications/configurationResult
asReferenceID='AS000001'
nidDduration='1d'
}]
}
First of all Sorry for duplicate question but i didn't get the answer I was looking for.I am getting the above error on console
Firefox can't establish a connection to the server at ws://localhost:8080/websocket.
here is my jsp page
var username;
var wsUri = "ws://localhost:8080/chat/websocket";
var websocket = new WebSocket(wsUri);
websocket.onopen = function (evt) {
onOpen(evt);
};
websocket.onmessage = function (evt) {
onMessage(evt);
};
websocket.onerror = function (evt) {
onError(evt);
};
var output = document.getElementById("output");
function join() {
alert('join start');
username = textField.value;
websocket.send(username + " joined");
alert('join end');
}
function send_message() {
alert('sendmessage start');
websocket.send(username + ": " + textField.value);
alert('sendmessage end');
}
function onOpen() {
alert('onopen start');
writeToScreen("Connected to " + wsUri);
alert('onopen end');
}
function onMessage(evt) {
console.log("onMessage");
writeToScreen("RECEIVED: " + evt.data);
if (evt.data.indexOf("joined") !== -1) {
userField.innerHTML += evt.data.substring(0, evt.data.indexOf(" joined")) + "\n";
} else {
chatlogField.innerHTML += evt.data + "\n";
}
}
function onError(evt) {
writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
}
function writeToScreen(message) {
output.innerHTML += message + "<br>";
}
Here is my java class
#ServerEndpoint(value = "/websocket")
public class ChatEndpoint {
private static final Set < Session > peers = Collections.synchronizedSet(new HashSet < Session > ());
#OnOpen
public void onOpen(Session peer) {
System.out.println("I am onOpen");
peers.add(peer);
}
#OnClose
public void onClose(Session peer) {
System.out.println("I am onClose");
peers.remove(peer);
}
#OnMessage
public void message(String message, Session client) throws IOException, EncodeException {
System.out.println("I am message");
for (Session peer: peers) {
peer.getBasicRemote().sendObject(message);
}
}
}
I am using Maven repository and trying to run this project for client to client interaction in java.
I'm trying to make some functional tests for my webapplication that is using Play 2.1.4 and Socialsecure. Before using securesocial the tests where pretty straight forward but now im having troubles figuering out how i can make tests on the secured actions.
#Test
public void createNewNote() {
Result result;
// Should return bad request if no data is given
result = callAction(
controllers.routes.ref.Notes.newNote(),
fakeRequest().withFormUrlEncodedBody(
ImmutableMap.of("title", "", "text",
"")));
assertThat(status(result)).isEqualTo(BAD_REQUEST);
result = callAction(
controllers.routes.ref.Notes.newNote(),
fakeRequest().withFormUrlEncodedBody(
ImmutableMap.of("title", "My note title", "text",
"My note content")));
// Should return redirect status if successful
assertThat(status(result)).isEqualTo(SEE_OTHER);
assertThat(redirectLocation(result)).isEqualTo("/notes");
Note newNote = Note.find.where().eq("title", "My note title")
.findUnique();
// Should be saved to DB
assertNotNull(newNote);
assertEquals("My note title", newNote.title);
assertEquals("My note content", newNote.text);
}
As of right now i got a user in the test yml file:
- !!models.User
id: 1234567890
username: Pingu
provider: Twitter
firstName: Pingu
lastName: Pingusson
email: pingu#note.com
password: password
My user is pretty straight forward...:
#Table(
uniqueConstraints=
#UniqueConstraint(columnNames={"username"}))
#Entity
public class User extends Model {
private static final long serialVersionUID = 1L;
#Id
public String id;
public String provider;
public String firstName;
public String lastName;
public String email;
public String password;
#MinLength(5)
#MaxLength(20)
public String username;
public static Finder<String, User> find = new Finder<String, User>(
String.class, User.class);
public static User findById(String id) {
return find.where().eq("id", id).findUnique();
}
public static User findByEmail(String email) {
return find.where().eq("email", email).findUnique();
}
#Override
public String toString() {
return this.id + " - " + this.firstName;
}
}
and the UserService:
public class UserService extends BaseUserService {
public UserService(Application application) {
super(application);
}
#Override
public void doDeleteExpiredTokens() {
if (Logger.isDebugEnabled()) {
Logger.debug("deleteExpiredTokens...");
}
List<LocalToken> list = LocalToken.find.where().lt("expireAt", new DateTime().toString()).findList();
for(LocalToken localToken : list) {
localToken.delete();
}
}
#Override
public void doDeleteToken(String uuid) {
if (Logger.isDebugEnabled()) {
Logger.debug("deleteToken...");
Logger.debug(String.format("uuid = %s", uuid));
}
LocalToken localToken = LocalToken.find.byId(uuid);
if(localToken != null) {
localToken.delete();
}
}
#Override
//public Identity doFind(UserId userId) {
public Identity doFind(IdentityId identityId){
if (Logger.isDebugEnabled()) {
Logger.debug(String.format("finding by Id = %s", identityId.userId()));
}
User localUser = User.find.byId(identityId.userId());
Logger.debug(String.format("localUser = " + localUser));
if(localUser == null) return null;
SocialUser socialUser = new SocialUser(new IdentityId(localUser.id, localUser.provider),
localUser.firstName,
localUser.lastName,
String.format("%s %s", localUser.firstName, localUser.lastName),
Option.apply(localUser.email),
null,
new AuthenticationMethod("userPassword"),
null,
null,
Some.apply(new PasswordInfo("bcrypt", localUser.password, null))
);
if (Logger.isDebugEnabled()) {
Logger.debug(String.format("socialUser = %s", socialUser));
}
return socialUser;
}
#Override
public Identity doFindByEmailAndProvider(String email, String providerId) {
List<User> list = User.find.where().eq("email", email).eq("provider", providerId).findList();
if(list.size() != 1){
Logger.debug("found a null in findByEmailAndProvider...");
return null;
}
User localUser = list.get(0);
SocialUser socialUser =
new SocialUser(new IdentityId(localUser.email, localUser.provider),
localUser.firstName,
localUser.lastName,
String.format("%s %s", localUser.firstName, localUser.lastName),
Option.apply(localUser.email),
null,
new AuthenticationMethod("userPassword"),
null,
null,
Some.apply(new PasswordInfo("bcrypt", localUser.password, null))
);
return socialUser;
}
#Override
public Token doFindToken(String token) {
if (Logger.isDebugEnabled()) {
Logger.debug("findToken...");
Logger.debug(String.format("token = %s", token));
}
LocalToken localToken = LocalToken.find.byId(token);
if(localToken == null) return null;
Token result = new Token();
result.uuid = localToken.uuid;
result.creationTime = new DateTime(localToken.createdAt);
result.email = localToken.email;
result.expirationTime = new DateTime(localToken.expireAt);
result.isSignUp = localToken.isSignUp;
if (Logger.isDebugEnabled()) {
Logger.debug(String.format("foundToken = %s", result));
}
return result;
}
#Override
public Identity doSave(Identity user) {
if (Logger.isDebugEnabled()) {
Logger.debug("save...!_!");
Logger.debug(String.format("user = %s", user));
}
User localUser = null;
localUser = User.find.byId(user.identityId().userId());
Logger.debug("id = " + user.identityId().userId());
Logger.debug("provider = " + user.identityId().providerId());
Logger.debug("firstName = " + user.firstName());
Logger.debug("lastName = " + user.lastName());
Logger.debug(user.fullName() + "");
Logger.debug("email = " + user.email());
Logger.debug(user.email().getClass() + "");
if (localUser == null) {
Logger.debug("adding new...");
localUser = new User();
localUser.id = user.identityId().userId();
localUser.provider = user.identityId().providerId();
localUser.firstName = user.firstName();
localUser.lastName = user.lastName();
//Temporary solution for twitter which does not have email in OAuth answer
if(!(user.email().toString()).equals("None")){
localUser.email = user.email().get();
}
if(!(user.passwordInfo() + "").equals("None")){
localUser.password = user.passwordInfo().get().password();
}
localUser.save();
} else {
Logger.debug("existing one...");
localUser.id = user.identityId().userId();
localUser.provider = user.identityId().providerId();
localUser.firstName = user.firstName();
localUser.lastName = user.lastName();
//Temporary solution for twitter which does not have email in OAuth answer
if(!(user.email().toString()).equals("None")){
localUser.email = user.email().get();
}
if(!(user.passwordInfo() + "").equals("None")){
localUser.password = user.passwordInfo().get().password();
}
localUser.update();
}
return user;
}
#Override
public void doSave(Token token) {
LocalToken localToken = new LocalToken();
localToken.uuid = token.uuid;
localToken.email = token.email;
try {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
localToken.createdAt = df.parse(token.creationTime.toString("yyyy-MM-dd HH:mm:ss"));
localToken.expireAt = df.parse(token.expirationTime.toString("yyyy-MM-dd HH:mm:ss"));
} catch (ParseException e) {
Logger.error("UserService.doSave(): ", e);
}
localToken.isSignUp = token.isSignUp;
localToken.save();
}
}
As of my understanding i should in someway set the session so the user is logged in by using the .withsession method on the fakerequest and maybe also set some value on the serverside.
Tried searching the web for examples using securesocial and play but found no tests at all.
How can i login in my user so i can preform the tests?
Best regards
Rawa
Thanks to David Weinbergs comment i was able to solve this after some trail and error. (:
I started out my LocalUser implementation from this reply:
https://stackoverflow.com/a/18589402/1724097
This is how i solved it:
To make unit tests i created a local user in the database, using the test-data.yml file:
- !!models.LocalUser
id: 1234567890
username: Username
provider: userpass
firstName: firstName
lastName: lastName
email: user#example.com
#hash for "password"
password: $2a$10$.VE.rwJFMblRv2HIqhZM5.CiqzYOhhJyLYrKpMmwXar6Vp58U7flW
Then i made a test utils class that create my fakeCookie.
import models.LocalUser;
import play.Logger;
import securesocial.core.Authenticator;
import securesocial.core.IdentityId;
import securesocial.core.SocialUser;
import securesocial.core.PasswordInfo;
import scala.Some;
import securesocial.core.AuthenticationMethod;
import scala.Option;
import scala.util.Right;
import scala.util.Either;
import play.mvc.Http.Cookie;
public class Utils {
public static Cookie fakeCookie(String user){
LocalUser localUser = LocalUser.findByEmail(user);
Logger.debug("Username: " + localUser.username +" - ID: " + localUser.id);
SocialUser socialUser = new SocialUser(new IdentityId(localUser.id, localUser.provider),
localUser.firstName,
localUser.lastName,
String.format("%s %s", localUser.firstName, localUser.lastName),
Option.apply(localUser.email),
null,
new AuthenticationMethod("userPassword"),
null,
null,
Some.apply(new PasswordInfo("bcrypt", localUser.password, null))
);
Either either = Authenticator.create(socialUser);
Authenticator auth = (Authenticator) either.right().get();
play.api.mvc.Cookie scalaCookie = auth.toCookie();
//debug loggig
Logger.debug("Cookie data:");
Logger.debug("Name: " + "Value: " + auth.cookieName() + " | Class: " + auth.cookieName().getClass() + " | Should be type: " + "java.lang.String");
Logger.debug("Value: " + "Value: " + scalaCookie.value() + " | Class: " + scalaCookie.value().getClass() + " | Should be type: " + "java.lang.String");
Logger.debug("MaxAge: " + "Value: " + scalaCookie.maxAge() + " | Class: " + scalaCookie.maxAge().getClass() + " | Should be type: " + "int");
Logger.debug("Path: " + "Value: " + scalaCookie.path() + " | Class: " + scalaCookie.path().getClass() + " | Should be type: " + "java.lang.String");
Logger.debug("Domain: " + "Value: " + scalaCookie.domain() + " | Class: " + auth.cookieDomain().getClass() + " | Should be type: " + "java.lang.String");
Logger.debug("Secure: " + "Value: " + auth.cookieSecure() + " | Class: " + "Boolean" + " | Should be type: " + "boolean");
Logger.debug("HttpOnly: " + "Value: " + auth.cookieHttpOnly() + " | Class: " + "Boolean" + " | Should be type: " + "boolean");
// secureSocial doesnt seem to set a maxAge or Domain so i set them myself.
Cookie fakeCookie = new Cookie(auth.cookieName(), scalaCookie.value(), 120, scalaCookie.path(), "None", auth.cookieSecure(), auth.cookieHttpOnly());
return fakeCookie;
}
}
And then i simply use my cookie to in the fakeRequest so im logged in:
Cookie cookie = Utils.fakeCookie("user#example.com");
Result result = callAction(
controllers.routes.ref.yourSampleClass.yourSecuredFucntion(),
fakeRequest().withFormUrlEncodedBody(
ImmutableMap.of("Value", "Some input value")).withCookies(cookie));
// Should return redirect status if successful
assertThat(status(result)).isEqualTo(SEE_OTHER);
assertThat(redirectLocation(result)).isEqualTo("/yourWantedResult");
Hope this helps others!