I'v followed this tutorial
to make Scala Plaframework application work with depending module that has 'println' message in it.
So,
myApp depends on myModule, in myMyModule' controller I have:
object MyLogger {
def log(message: String) {
Console.println("something" + message)
}
}
In myApp I have:
object Application extends Controller {
def index = Action {
MyLogger.log("Here's my log message");
Ok(views.html.index("Your new application is ready."))
}
}
I go to localhost:9000, and I'm expecting 'Here's my log message' to be in my output, but there is no any, except:
[info] play - Listening for HTTP on port 9000...
(Server started, use Ctrl+D to stop and go back to the console...)
I' have checked:
cd myApp;
play dependencies (myApp it really depends on myModule, so it should work)
--
After some investigation I found that until I delete dependency to myDev, this message 'this is an info' in MyApp index controller was not showed as well. And then, when I delete that dependency, the application stars reacting to my changes again:
def index = Action {
play.api.Logger.info("this is an info")
Ok(views.html.index("Your new application is ready!"))
}
So, maybe I defined my module using wrong way. Should I change the structure of the myModule? or it is possible to leave it like a default project structure? I will check it later. I guess the reason is with 'routes' file wich I leave in my MyModule.
Why won't you use play.api.Logger ?
It allows you to log to the different levels - depending on your application.conf and app mode settings:
def index = Action {
play.api.Logger.info("this is an info")
play.api.Logger.debug("and debug is also possible")
play.api.Logger.error("...and error")
play.api.Logger.warn("or even warn")
Ok(views.html.index("Your new application is ready."))
}
dev mode displays all levels by default and life will avoid displaying the debug
The reason why I had this problem, is because myModule was an application, but not a module. I had to:
delete 'routes' file
clean up 'application.conf' file
delete 'views' folder
Then I can call this a module, but not application.
I guess it woud be better If play has something like this: play newModule. Maybe it has?
(So, I just missed this part about 'routes', that actually was described in the tutorial above. Too lazy to read.. :(. Play framework 1.x works similar to that, regarding the modules. )
Related
See working Java code at bottom.
I'm trying to create an SSE connection testing scenario that uses a client ID that is the response to a previous REST POST call. Here's the Scala code:
package computerdatabase
import io.gatling.core.Predef._
import io.gatling.http.Predef._
class ssetest extends Simulation {
val registration = scenario("registration")
.exec(http("endpoint1")
.post("http://localhost:7070/api/register")
.body(RawFileBody("./Stocks.json")).asJson
.check(status is 201)
.check(jsonPath("$.id").saveAs("clientId")))
setUp(scn.inject(constantUsersPerSec(200).during(180))).assertions(global.failedRequests.count.is(0))
val sseConnection = scenario("ServerSentEvents")
.exec { session =>
sse("GET messages")
.connect("/api/sse/" + session("clientId").as[String])
.await(1)(
sse.checkMessage("ConnectionCheck").matching(substring("connection established"))
.check(bodyString.saveAs("InitialMessage"))
)
}
}
I would like to use the client ID saved into the Session in the first scenario, to configure the SSE endpoint to connect to in the second one. Presently, when running the scenario, I'm getting:
19:35:50.086 [ERROR] i.g.c.ZincCompiler$ - /home/dingo/Downloads/gatling-charts-highcharts-bundle-3.7.6/user-files/simulations/computerdatabase/SseSimulation.scala:21:15: type mismatch;
found : io.gatling.http.request.builder.sse.SseConnectRequestBuilder
required: io.gatling.commons.validation.Validation[io.gatling.core.session.Session]
.await(1)(
^
19:35:50.135 [ERROR] i.g.c.ZincCompiler$ - one error found
19:35:50.145 [ERROR] i.g.c.ZincCompiler$ - Compilation crashed
xsbt.InterfaceCompileFailed: null
at xsbt.CachedCompiler0.handleErrors(CompilerBridge.scala:183)
at xsbt.CachedCompiler0.run(CompilerBridge.scala:172)
at xsbt.CachedCompiler0.run(CompilerBridge.scala:134)
at xsbt.CompilerBridge.run(CompilerBridge.scala:39)
at sbt.internal.inc.AnalyzingCompiler.compile(AnalyzingCompiler.scala:91)
at sbt.internal.inc.MixedAnalyzingCompiler.$anonfun$compile$7(MixedAnalyzingCompiler.scala:192)
at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.scala:18)
at sbt.internal.inc.MixedAnalyzingCompiler.timed(MixedAnalyzingCompiler.scala:247)
at sbt.internal.inc.MixedAnalyzingCompiler.$anonfun$compile$4(MixedAnalyzingCompiler.scala:182)
at sbt.internal.inc.MixedAnalyzingCompiler.$anonfun$compile$4$adapted(MixedAnalyzingCompiler.scala:163)
at sbt.internal.inc.JarUtils$.withPreviousJar(JarUtils.scala:239)
at sbt.internal.inc.MixedAnalyzingCompiler.compileScala$1(MixedAnalyzingCompiler.scala:163)
at sbt.internal.inc.MixedAnalyzingCompiler.compile(MixedAnalyzingCompiler.scala:210)
at sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileInternal$1(IncrementalCompilerImpl.scala:528)
at sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileInternal$1$adapted(IncrementalCompilerImpl.scala:528)
at sbt.internal.inc.Incremental$.$anonfun$apply$5(Incremental.scala:177)
at sbt.internal.inc.Incremental$.$anonfun$apply$5$adapted(Incremental.scala:175)
at sbt.internal.inc.Incremental$$anon$2.run(Incremental.scala:461)
at sbt.internal.inc.IncrementalCommon$CycleState.next(IncrementalCommon.scala:116)
at sbt.internal.inc.IncrementalCommon$$anon$1.next(IncrementalCommon.scala:56)
at sbt.internal.inc.IncrementalCommon$$anon$1.next(IncrementalCommon.scala:52)
at sbt.internal.inc.IncrementalCommon.cycle(IncrementalCommon.scala:263)
at sbt.internal.inc.Incremental$.$anonfun$incrementalCompile$8(Incremental.scala:416)
at sbt.internal.inc.Incremental$.withClassfileManager(Incremental.scala:503)
at sbt.internal.inc.Incremental$.incrementalCompile(Incremental.scala:403)
at sbt.internal.inc.Incremental$.apply(Incremental.scala:169)
at sbt.internal.inc.IncrementalCompilerImpl.compileInternal(IncrementalCompilerImpl.scala:528)
at sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileIncrementally$1(IncrementalCompilerImpl.scala:482)
at sbt.internal.inc.IncrementalCompilerImpl.handleCompilationError(IncrementalCompilerImpl.scala:332)
... 5 common frames omitted
Wrapped by: sbt.internal.inc.CompileFailed: Compilation failed
at sbt.internal.inc.IncrementalCompilerImpl.handleCompilationError(IncrementalCompilerImpl.scala:335)
at sbt.internal.inc.IncrementalCompilerImpl.compileIncrementally(IncrementalCompilerImpl.scala:420)
at sbt.internal.inc.IncrementalCompilerImpl.compile(IncrementalCompilerImpl.scala:137)
at io.gatling.compiler.ZincCompiler$.doCompile(ZincCompiler.scala:218)
at io.gatling.compiler.ZincCompiler$.main(ZincCompiler.scala:226)
at io.gatling.compiler.ZincCompiler.main(ZincCompiler.scala)
How can I fix this?
Disclaimer: I don't know Scala.
Actions taken:
Created a new folder structure for Gatling in my project
Put the simulation class in ./src/gatling/java/computerdatabase
Put Stocks.json in ./src/gatling/resources/Stocks.json and made the file path in the code absolute
Added the Gatling Gradle plugin to build.gradle
Checked this example Simulation for inspiration
Fiddled around a bit with the code, reading about Session function syntax
package computerdatabase;
import io.gatling.javaapi.core.ScenarioBuilder;
import io.gatling.javaapi.core.Simulation;
import io.gatling.javaapi.http.HttpProtocolBuilder;
import static io.gatling.javaapi.core.CoreDsl.*;
import static io.gatling.javaapi.http.HttpDsl.*;
public class SseSimulation extends Simulation {
HttpProtocolBuilder httpProtocol = http
.baseUrl("http://localhost:7070");
ScenarioBuilder scn = scenario("Scenario Name")
.exec(http("client id registration")
.post("/api/register/")
.body(RawFileBody("Stocks.json")).asJson()
.check(status().is(201))
.check(jsonPath("$.id").saveAs("clientId")))
.exec(
sse("open channel")
.connect(session -> "/api/sse/" + session.getString("clientId"))
);
{
setUp(scn.injectOpen(constantUsersPerSec(200).during(1)).protocols(httpProtocol)).assertions(global().failedRequests().count().is(0L));
}
}
Disclaimer: I don't know Scala.
Then switch to Java. Gatling 3.7 (that you're using) supports it as well and both the official documentation and the official online courses explain it very well.
Lots of things wrong:
the code you've provided can't possibly compile. There's nothing named scn in there. Please fix it so one can help you.
your compile error has nothing to do with the piece of code you've provided. The compiler complains about an error in SseSimulation while you've provided a class named ssetest. Again, please first fix your code sample
RawFileBody("./Stocks.json") is wrong. You shouldn't use a relative path. Let the ClassLoader resolve your files. This Stocks.json file should go in user-files/resources and you should write RawFileBody("Stocks.json")
Checks save data into the Session of the virtual user that executed the request. You can't use different scenarios because they would execute different sets of virtual users. You have to perform register and SSE connect in the same scenario.
I recommend that you should invest some time in reading the documentation and checking the online courses, you will ultimately save a lot of time.
I'm currently researching a way in which I can implement a screen capture method in my acceptance test suite in Scala Cucumber after each step definition is completed in the scenario.
I have already implemented a method that will take a screenshot of a webpage if one of the automation test fails by invoking the method in the after hooks class. This does work fine but this will only capture the web page once the entire scenario has been completed.
I wasn't sure if there was something like before and after hooks that could be applied to the steps instead of the scenario.
Hooks.scala
#After
def tearDown(result: Scenario){
if (result.isFailed) {
ifCurrentDriverTakesSnapshot {
takesSnapshot =>
Snapshotter.takeErrorSnapshot(takesSnapshot, result)
}
}
Snapshotter.Scala
def takeErrorSnapshot(takesScreenshot: TakesScreenshot, result: Scenario)
= {
try {
val screenshot = takesScreenshot.getScreenshotAs(OutputType.BYTES)
result.embed(screenshot, "image/png")
}
catch {
case e: WebDriverException =>
e.printStackTrace(System.err)
}
}
I would like to be able to do this in a class or method that can be called after each new page is opened or after each step definition. I could right a step definition that would handle the screen capture but I would like to do in a better way as I have 100's of test scenarios so it would be better to avoid adding a step for this in between every step definition as they have done in the below link.
Cucumber Java screenshots
If anyone could share some light on the matter i'd greatly appreciate it as I'm struggling to find much on the subject.
Thanks!!!
I know that the earlier versions of Play used to support routes and conditionals (if blocks) in the routes file but I cannot find any such documentation for Play 2.2.x and HTTP routing says nothing about such a feature.
I want to replace this:
GET /api/users/:id com.corporate.project.controllers.UserController.get(id)
with a shorter version using import as follows:
import com.corporate.project.controllers._
GET /api/users/:id UserController.get(id)
Also, is it possible to have conditionals in the routes file? e.g.
if Play.isDev(Play.current())
GET /displayConfig DebugController.displayServerConfigs()
Package imports used to be possible with an SBT setting: routesImport += "com.corporate.project.controllers._". Not sure if it is still the case.
Also, is it possible to have conditionals in the routes file?
It might not be an ideal solution but we use routes tags to deal with this kind of conditional routes. You need a filter that checks if the route is annotated and runs your conditional logic.
Routes:
# #devmode
GET /displayConfig DebugController.displayServerConfigs()
Filter:
object DevmodeRouteFilter extends Filter {
private val DevmodeAnnotation = "#devmode"
override def apply(next: RequestHeader => Future[SimpleResult])(request: RequestHeader): Future[SimpleResult] = {
if(isDevRoute(request) && !Play.isDev(Play.current()) {
Play.current.global.onHandlerNotFound(request)
} else {
next(request)
}
}
private def isDevRoute(request: RequestHeader): Boolean = {
val comments = request.tags.getOrElse(Routes.ROUTE_COMMENTS, "")
comments.lines.exists { comment =>
comment.trim == DevmodeAnnotation
}
}
}
Don't forget to add the filter to the filter chain.
Thank you for your question, it is an interesting idea, so I went to the sources of Play2 and found that in my checkout of Play 2.2.3 in the play.core.Router.scala: object HandlerInvoker constructs controller as
handlerDef.ref.getClass.getClassLoader.loadClass(handlerDef.controller)
So I am afraid that support for partial class names (stored in handlerDef.controller) is not implemented in 2.2.x.
In 2.3.x there is commit https://github.com/playframework/playframework/commit/ba98dabd7ba374ed98f14f721835b898d27dd55b
that brought notion of package/namespace for the routes.
Please see changes in Routes.scala and RoutesCompiler.scala from that commit.
But I can't find description of that functionality in the documentation and I do not have Play 2.3.x to play with it now.
P.S.: Sample magic for advanced routing for 2.3.x described in http://java.dzone.com/articles/advanced-routing-play .
When i run my junit jersey service tests using the grizzly framework in eclipse, the log is directed to stderr. As a result the console window grabs focus, and the log appears red.
I can't figure out the proper configuration steps. From my reading it looks like i need to add the slf4j.jar to my pom.xml and add a logging properties file somewhere? But i'm unsure which slf4j jars to add (there are many) or where to place the logging properties file.
Or, frankly, if this is the right approach in general.
p.s. also i am aware i can turn off the "show console when standard error changes" feature in eclipse, but i'd rather not paint over the problem. :)
It doesn't look to me like Grizzly used slf4j, but rather the "standard" java.util.logging framework. If that's the case, you can read about configuring it here: http://docs.oracle.com/javase/6/docs/technotes/guides/logging/overview.html#1.8
With Eric's help above I created this class:
package org.trebor.www;
import java.util.logging.ConsoleHandler;
import java.util.logging.Handler;
import java.util.logging.Logger;
public class LoggerTrap
{
public LoggerTrap()
{
Handler handler =
new ConsoleHandler()
{
{
setOutputStream(System.out);
}
};
Logger.getLogger("").addHandler(handler);
}
}
and added this jvm arg
-Djava.util.logging.config.class=org.trebor.www.LoggerTrap
and all java.logging goes to STDOUT. In the process I've learned that I don't much like java.logging.
Has anyone tried to do a scala/lift application using MVC instead of view-first?
I know that you can create Controllers/views as:
package test.test.test.view
...
Lots of imports
...
class MvcRocks extends LiftView {
def dispatch = {
case "rule" => ruleDispatch _
case "bar" => barDispatch _
}
def barDispatch(): Box[NodeSeq] = {
Full(<lift:embed what="/mvc_rucks/bar" />)
}
}
And this code will be accessible if you add it to the menu(in the boot), even if its hidden as:
val entries = Menu(Loc("Home", List("index"), "Home")) ::
List(Menu(Loc("MvcRock", List("mvc_rocks", "bar"), "Mvc really Rocks", Hidden)))
LiftRules.setSiteMap(SiteMap(entries:_*))
Now, of course this will make it so, you declare every action in the menu, then have a case for each action(per controller) and that would open the "view" (that would be a file in /mvc_rucks/bar.html).
My question is, if you would implement a full mvc, you would need to put all your logic in the action barDispatch, but how would you send those variables to the HTML template? and how would you receive post/get information?
(Notice that if you html code has lift bindings, it will of course act as view-first, even after you did MVC before).
Since your question is not specific to Lift, I'd recommend you the Playframework. The version 1.1 supports Scala 2.8.
Playframework is totally MVC with a fantastic template engine and allows you to choose freely between java/scala.
And I say: To use Play, you don't need 'nuclear scientist knowledge'. Try it!