I would like to use WebSockets in Scala and Play Framework. But I can't get the Echo-server example to work.
What should I import for await() and disconnect()?
The error I get is Error raised is : not found: value await. I used the code below:
package controllers
import play._
import play.mvc._
import play.mvc.Http.WebSocketEvent
import play.mvc.Http.WebSocketFrame
import play.mvc.Http.WebSocketClose
import play.mvc.WebSocketController
object MySocket extends WebSocketController {
def echo = {
while(Http.Inbound.current().isOpen()) {
val e : WebSocketEvent =
await(Http.Inbound.current().nextEvent()).asInstanceOf[WebSocketEvent]
if(e.isInstanceOf[WebSocketFrame]) {
val frame : WebSocketFrame = e.asInstanceOf[WebSocketFrame]
if(!frame.isBinary) {
if(frame.textData.equals("quit")) {
Http.Outbound.current().send("Bye!");
disconnect();
} else {
Http.Outbound.current().send("Echo: " + frame.textData)
}
}
}
if(e.isInstanceOf[WebSocketClose]) {
Logger.info("Socket closed!")
}
}
}
}
Here is the compilation error in the Terminal:
Compiling:
/Users/jonas/play-1.2.2RC1/jonassite/app/MySocket.scala
/Users/jonas/play-1.2.2RC1/jonassite/app/MySocket.scala:14: not found: value await
val e : WebSocketEvent = await(Http.Inbound.current().nextEvent()).asInstanceOf[WebSocketEvent]
^
/Users/jonas/play-1.2.2RC1/jonassite/app/MySocket.scala:20: not found: value disconnect
disconnect();
^
two errors found
Compiling:
/Users/jonas/play-1.2.2RC1/jonassite/app/MySocket.scala
/Users/jonas/play-1.2.2RC1/jonassite/app/MySocket.scala:14: not found: value await
val e : WebSocketEvent = await(Http.Inbound.current().nextEvent()).asInstanceOf[WebSocketEvent]
^
/Users/jonas/play-1.2.2RC1/jonassite/app/MySocket.scala:20: not found: value disconnect
disconnect();
^
two errors found
12:52:57,049 ERROR ~
#66lce6kp8
Internal Server Error (500) for request GET /handshake
Compilation error (In /app/MySocket.scala around line 14)
The file /app/MySocket.scala could not be compiled. Error raised is : not found: value await
play.exceptions.CompilationException: not found: value await
at play.scalasupport.ScalaPlugin.compilationException(ScalaPlugin.scala:129)
at play.scalasupport.ScalaPlugin.detectClassesChange(ScalaPlugin.scala:115)
at play.plugins.PluginCollection.detectClassesChange(PluginCollection.java:358)
at play.Play.detectChanges(Play.java:591)
at play.Invoker$Invocation.init(Invoker.java:186)
at Invocation.HTTP Request(Play!)
await() and disconnect() are methods available from the WebSocketController. However, these are currently only available in the Java version, and not Scala. See this post here on the play groups for more information.
This should be available in the 1.0 release of the scala plugin, but for now if you want to use the aysnc features (await etc), then you will have to use Java, or take a look at the Java wrapper that one of the Play users have developed.
Related
Is there some configuration/android version/phone model/etc. in which Random.secure() can throw an unsupported error for real?
https://api.dart.dev/stable/2.18.3/dart-math/Random/Random.secure.html
says:
"If the program cannot provide a cryptographically secure source of random numbers, it throws an UnsupportedError".
If you want to be sure, you'll have to take a look inside the code, wich extends the abstract class Random.
I found the following unit test in the dart sources:
https://github.com/dart-lang/sdk/blob/main/tests/lib/math/random_secure_unsupported_test.dart
// Test that `Random.secure()` throws `UnsupportedError` each time it fails.
import "package:expect/expect.dart";
import 'dart:math';
main() {
var result1 = getRandom();
var result2 = getRandom();
Expect.isNotNull(result1);
Expect.isNotNull(result2); // This fired for http://dartbug.com/36206
Expect.equals(result1 is Random, result2 is Random);
Expect.equals(result1 is UnsupportedError, result2 is UnsupportedError);
}
dynamic getRandom() {
try {
return Random.secure();
} catch (e) {
return e;
}
}
Calling Random.secure() two times in a row seems to cause an issue as described in http://dartbug.com/36206, but only for IE browser and Dart2JS.
I am running into an issue where I'm getting an error when I am trying to develop a method to generate a simulation.log whenever I receive a status other than 200 and receive "KO". I was wondering if there is any solution in solving this issue?
Error:
scala:8: not found: type ExtraInfo
def getExtraInfo(extraInfo : ExtraInfo): String = {
Code:
def getExtraInfo(extraInfo : ExtraInfo): String = {
if (isDebug
|| extraInfo.response.statusCode.get != TestData.successStatus
|| extraInfo.status.eq(Status.apply("KO"))) {
",URL:" + extraInfo.request.getUrl +
" Request: " + extraInfo.request.getStringData +
" Response: " + extraInfo.response.body.string
}
else
{
""
}
}
The scala type error could be caused by a missing import.
Try adding the following to your code -
import io.gatling.http.request._
You may also need to add import io.gatling.commons.stats._ for Status if you don't have it already
I found out according from Stephane message
"You seem to be running Gatling master.
ExtraInfo is going away in Gatling 3, as it wasn't used in any official Gatling component and was a huge source of bugs."
I have followed the tutorial given by Amazon here but it seems that my code failed to run.
The error that I got:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
The method withJobFlowRole(String) is undefined for the type AddJobFlowStepsRequest
at main.main(main.java:38)
My full code:
import java.io.IOException;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.PropertiesCredentials;
import com.amazonaws.services.elasticmapreduce.*;
import com.amazonaws.services.elasticmapreduce.model.AddJobFlowStepsRequest;
import com.amazonaws.services.elasticmapreduce.model.AddJobFlowStepsResult;
import com.amazonaws.services.elasticmapreduce.model.HadoopJarStepConfig;
import com.amazonaws.services.elasticmapreduce.model.StepConfig;
import com.amazonaws.services.elasticmapreduce.util.StepFactory;
public class main {
public static void main(String[] args) {
AWSCredentials credentials = null;
try {
credentials = new PropertiesCredentials(
main.class.getResourceAsStream("AwsCredentials.properties"));
} catch (IOException e1) {
System.out.println("Credentials were not properly entered into AwsCredentials.properties.");
System.out.println(e1.getMessage());
System.exit(-1);
}
AmazonElasticMapReduce client = new AmazonElasticMapReduceClient(credentials);
// predefined steps. See StepFactory for list of predefined steps
StepConfig hive = new StepConfig("Hive", new StepFactory().newInstallHiveStep());
// A custom step
HadoopJarStepConfig hadoopConfig1 = new HadoopJarStepConfig()
.withJar("s3://mywordcountbuckett/binary/WordCount.jar")
.withMainClass("com.my.Main1") // optional main class, this can be omitted if jar above has a manifest
.withArgs("--verbose"); // optional list of arguments
StepConfig customStep = new StepConfig("Step1", hadoopConfig1);
AddJobFlowStepsResult result = client.addJobFlowSteps(new AddJobFlowStepsRequest()
.withJobFlowRole("jobflow_role")
.withServiceRole("service_role")
.withSteps(hive, customStep));
System.out.println(result.getStepIds());
}
}
What could be the reason that the code is not running ?
Are there any tutorials based on the latest version ?
I have set up a test app on bitbucket that reproduces my issue:
https://bitbucket.org/LuisMuniz/grails-bug-notacceptable
I have fairly standard REST controller action (save) that returns a http response status of 201 (CREATED).
When I run a functional test, everything works out as expected, with a http status of 201.
When I run a unit test standalone, with grailsw, the controller behaves as expected, returning code 201.
When I run the same unit test inside Intellij IDEA (tried with latest 14.x and latest 15 EAP versions), the controller returns http code 406 (NOT_ACCEPTABLE)
I have debugged the test execution and have found that it comes to the mimeTypes inside the applicationContext, that only contain a single entry: text/html.
Does anyone know why this is happening? Is this a known issue?
Is there a way to fix this or else is there something I can do to make Intellij unit tests not fail or maybe use a Junit Rule to skip these tests if they are executed in Intellij?
Update
Upon demand, posting the code here.
package na
import grails.rest.RestfulController
import org.springframework.http.HttpStatus
class MyController extends RestfulController {
static responseFormats = ['json']
static allowedMethods = [save: "POST"]
def save() {
response.status=HttpStatus.CREATED.value()
respond request.JSON
}
}
Functional test (this passes):
package na
import grails.util.Holders
import org.codehaus.groovy.grails.commons.GrailsApplication
import org.springframework.context.ApplicationContext
import org.springframework.http.HttpStatus
import spock.lang.Specification
import wslite.rest.RESTClient
/**
* Created by lmuniz on 17/09/15.
*/
class MyControllerFuncSpec extends Specification {
def "Controller returns status 201"() {
given:
//noinspection GroovyAssignabilityCheck
def restClient = new RESTClient("http://localhost:8080/notacceptable")
when:
def response = restClient.post([path: "/my"]) {
json payload
}
then:
response.statusCode == HttpStatus.CREATED.value()
response.json == payload
where:
payload = [message: "Hello world"]
}
}
Unit Test (fails in IDEA):
package na
import grails.test.mixin.TestFor
import spock.lang.Specification
import spock.lang.Unroll
import static org.springframework.http.HttpStatus.CREATED
import static org.springframework.http.HttpStatus.NOT_ACCEPTABLE
/**
* See the API for {#link grails.test.mixin.web.ControllerUnitTestMixin} for usage instructions
*/
#TestFor(MyController)
class MyControllerSpec extends Specification {
boolean runsInIntellij() {
System.getProperty('idea.launcher.port') != null
}
#Unroll
def "Controller responds with http code #expectedResponseCode when it is running #inEnvironment"(){
given:
println System.getProperties().collect {it.toString()}.join('\n')
request.method = 'POST'
request.json = [message:"Hello world"]
when:
controller.save()
then:
response.status == expectedResponseCode
where:
expectedResponseCode = (runsInIntellij() ? NOT_ACCEPTABLE.value() : CREATED.value())
inEnvironment = (runsInIntellij() ? 'inside Intellij' : 'standalone')
}
}
In your controller, instead of
respond request.JSON
Can you try with this:
render(status: response.status)
In Play, if an in thrown in initializing a class - for example, configuration.get("badKey").get being called, I believe there is a java.lang.ExceptionInInitializerError. However, no error is ever caught or logged by Play and it just goes on, broken.
How can I make sure this is caught, or logged, or something other than just ignored?
It brings the website to halt, but I don't know that it's happened.
I know that I shouldn't have these errors in the first place. What first prompted this is that the Application.conf file differs depending on if its my local environment or production. If a developer forgets to add a key to the production one, it can bring the website to a halt (silently). Conceivably, though, there could be other errors too.
You can use play's built in Logger.
import play.Logger
try {
configuration.get("badKey").get
} catch {
case e:ExceptionInInitializerError => {
Logger.error("ExceptionInInitializerError")
Logger.error(e.getMessage())
}
case e:Exception => {
Logger.error("Exception")
Logger.error(e.getMessage())
}
}
Or write an accessor that goes to a default or logs an error without needing a try catch
import play.Logger
import play.api.Play
object Conf {
private val config = Play.current.configuration
def get(key:String):String =
config.getString(key) match {
case Some(value:String) => value
case _ => {
Logger.warn("No value found in application.conf for [" + key + "]")
"some default value"
}
}
}