Scalate ResourceNotFoundException in Scalatra - scala

I'm trying the following based on scalatra-sbt.g8:
class FooWeb extends ScalatraServlet with ScalateSupport {
beforeAll { contentType = "text/html" }
get("/") {
templateEngine.layout("/WEB-INF/scalate/templates/hello-scalate.jade")
}
}
but I'm getting the following exception (even though the file exists) - any clues?
Could not load resource: [/WEB-INF/scalate/templates/hello-scalate.jade]; are you sure it's within [null]?
org.fusesource.scalate.util.ResourceNotFoundException: Could not load resource: [/WEB-INF/scalate/templates/hello-scalate.jade]; are you sure it's within [null]?
FWIW, the innermost exception is coming from org.mortbay.jetty.handler.ContextHandler.getResource line 1142: _baseResource==null.

Got an answer from the scalatra mailing list. The problem was that I was starting the Jetty server with:
import org.mortbay.jetty.Server
import org.mortbay.jetty.servlet.{Context,ServletHolder}
val server = new Server(8080)
val root = new Context(server, "/", Context.SESSIONS)
root.addServlet(new ServletHolder(new FooWeb()), "/*")
server.start()
I needed to insert this before start():
root.setResourceBase("src/main/webapp")

Related

How to publish data to using MQTT

I used this docker image to install Mosquitto MQTT.
Now it's running and showing the following message in the terminal:
1515680808: mosquitto version 1.4.14 (build date Mon, 10 Jul 2017 23:48:43 +0100) starting
1515680808: Config loaded from /mqtt/config/mosquitto.conf.
1515680808: Opening websockets listen socket on port 9001.
1515680808: Opening ipv4 listen socket on port 1883.
1515680808: Opening ipv6 listen socket on port 1883.
Then I created a simple Maven project:
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-streaming-mqtt_2.11</artifactId>
<version>1.6.3</version>
</dependency>
I tried to publish some data to a topic using the code shown below. I point to localhost:1883 as the MqttBrokerUrl and a topic test. However, I get this error:
Exception in thread "main" java.lang.NullPointerException at
org.eclipse.paho.client.mqttv3.MqttConnectOptions.validateURI(MqttConnectOptions.java:457)
at
org.eclipse.paho.client.mqttv3.MqttAsyncClient.(MqttAsyncClient.java:273)
at
org.eclipse.paho.client.mqttv3.MqttAsyncClient.(MqttAsyncClient.java:167)
at
org.eclipse.paho.client.mqttv3.MqttClient.(MqttClient.java:224)
at org.test.MQTTPublisher$.main(MQTTPublisher.scala:37) at
org.test.MQTTPublisher.main(MQTTPublisher.scala)
Code:
package org.test
import org.apache.log4j.{Level, Logger}
import org.eclipse.paho.client.mqttv3._
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence
import org.apache.spark.storage.StorageLevel
import org.apache.spark.streaming.{Seconds, StreamingContext}
import org.apache.spark.streaming.mqtt._
import org.apache.spark.SparkConf
object MQTTPublisher {
def main(args: Array[String]) {
if (args.length < 2) {
System.err.println("Usage: MQTTPublisher <MqttBrokerUrl> <topic>")
System.exit(1)
}
// Set logging level if log4j not configured (override by adding log4j.properties to classpath)
if (!Logger.getRootLogger.getAllAppenders.hasMoreElements) {
Logger.getRootLogger.setLevel(Level.WARN)
}
val Seq(brokerUrl, topic) = args.toSeq
var client: MqttClient = null
try {
val persistence = new MemoryPersistence()
client = new MqttClient("localhost:1883", MqttClient.generateClientId(), persistence)
client.connect()
val msgtopic = client.getTopic(topic)
val msgContent = "test test test"
val message = new MqttMessage(msgContent.getBytes("utf-8"))
while (true) {
try {
msgtopic.publish(message)
println(s"Published data. topic: ${msgtopic.getName()}; Message: $message")
} catch {
case e: MqttException if e.getReasonCode == MqttException.REASON_CODE_MAX_INFLIGHT =>
Thread.sleep(10)
println("Queue is full, wait for to consume data from the message queue")
}
}
} catch {
case e: MqttException => println("Exception Caught: " + e)
} finally {
if (client != null) {
client.disconnect()
}
}
}
}
The MqttClient() constructor takes a URI.
What you have provided is just a hostname and port number (localhost:1883), it's missing a protocol section which should be tcp:// (which is what the library is expecting and getting null back. This really should throw a better error.)
You need to change the line to be
client = new MqttClient("tcp://localhost:1883", MqttClient.generateClientId(), persistence);
I think you are giving the wrong Url i.e you are not specifying the protocol over which it has to connect that is my hunch.
Try changing the url to :
tcp://localhost:1883
I think it would work ! Rest all seems fine to me.
For a working example See this : https://github.com/shiv4nsh/scala-mqtt-client-rasberrypi-starter-kit/blob/master/src/main/scala/com/knoldus/MQTTPublisher.scala

Swagger grails Integration

I am new to swagger and I want to integrate swagger to Restful API project using grails framework. Please help if anybody have any idea what i am doing wrong?
my grails specification as below:
| Grails Version: 3.0.7
| Groovy Version: 2.4.4
| JVM Version: 1.8.0_71
Did some settings for swagger as below:
in build.gradle:
dependencies {
...
compile "io.swagger:swagger-core:1.5.3"
compile "io.swagger:swagger-jaxrs:1.5.3"
...
}
in resources.groovy
import io.swagger.jaxrs.config.BeanConfig
beans = {
swaggerConfig(BeanConfig) {
def serverUrl = "http://localhost:8080/"
def hostName = "localhost:8080"
resourcePackage = "grails.rest.example"
host = hostName
basePath = "/api"
version = 'v0' // Default "1".
title = 'Core Registration API, Version V0'
description = 'API for Accessing secured resources'
contact = 'testtest#mailinator.com'
license = ''
licenseUrl = ''
}
corsFilter(CorsFilter)
}
Added a Controller ApiDocController.groovy:
package grails.rest.example.apidoc
import grails.web.mapping.LinkGenerator
class ApiDocController {
LinkGenerator grailsLinkGenerator
def apiDocService
def index = {
String basePath = grailsLinkGenerator.serverBaseURL
render(view: 'index', model: [apiDocsPath: "${basePath}/api/swagger-json"])
//render(view: 'index', model: [apiDocsPath: "localhost:8080/api/swagger-json"])
//render(view: 'index', model: [apiDocsPath: "localhost:8080/dist/index.html"])
}
def swaggerJson = {
render apiDocService.generateJSON()
}
}
Added a URLMapping for controller:
"/api/info"(controller: 'ApiDoc')
"/"(controller: 'Index')
"500"(controller: 'InternalServerError')
"404"(controller: 'NotFound')
Added a service ApiDocService.groovy:
//package com.care.apidoc
package grails.rest.example.apidoc
import io.swagger.jaxrs.config.BeanConfig
import grails.transaction.Transactional
import io.swagger.util.Json
#Transactional
class ApiDocService {
def swaggerConfig
/*
* generates SWAGGer JSON
*/
def generateJSON() {
String[] schemes = ["http"] as String[]
swaggerConfig.setSchemes(schemes)
swaggerConfig.setScan(true)
def swagger = swaggerConfig.getSwagger()
Json.mapper().writeValueAsString(swagger);
}
}
added Swagger-ui in src/main/webapp/dist folder
with a working customised API URL "http://localhost:8080/api/orders" in index.html
added CorsFilter setting in src/main/groovy/CorsFilter.groovy
import org.springframework.web.filter.OncePerRequestFilter
import javax.annotation.Priority
import javax.servlet.FilterChain
import javax.servlet.ServletException
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
#Priority(Integer.MIN_VALUE)
public class CorsFilter extends OncePerRequestFilter {
public CorsFilter() { }
#Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse resp, FilterChain chain)
throws ServletException, IOException {
String origin = req.getHeader("Origin");
boolean options = "OPTIONS".equals(req.getMethod());
resp.addHeader("Access-Control-Allow-Headers", "origin, authorization, accept, content-type, x-requested-with");
resp.addHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS");
resp.addHeader("Access-Control-Max-Age", "3600");
resp.addHeader("Access-Control-Allow-Origin", origin == null ? "*" : origin);
resp.addHeader("Access-Control-Allow-Credentials", "true");
if (!options) chain.doFilter(req, resp);
}
}
On starting the server.
API for orders is working correctly, however, when I try to load the API in Swagger UI index file. it shows.
No operations defined in spec!
as attached in a pics.
Have you looked at springfox?
Here is a sample Grails Application hosted in Heroku that demonstrates the capabilities of springfox integrating with it to produce the service description in the Open API specification 2.0 (fka swagger). The source code for the demo is available here.
You can see this demo running live here demonstrating the Open API specification generated by the grails application and rendered using swagger-ui.
The library that makes this possible is springfox-grails-integration library. It is about to be released and probably needs a little bit of work to make it a grails plugin. There is some preliminary documentation of how to configure this the library repository.
NOTE: This only works with grails 3.x
Also it was a notable library showcased in the SHOW US YOUR GRAILS contest. Feedback to improve this library is much appreciated.

Serving an entire directory tree with spray.io

I would like to translate this JS code to Scala, using spray.io.
How can I translate this line below to Scala using spray.io ?
app.use('/', express.static(path.join(__dirname, 'public')));
In other word, how can I serve an entire directory tree using spray.io ?
As comment above says Spray is deprecated. But directives are similar in akka-http. Here is what you probably need (getFromResourceDirectory in your case)
pathPrefix("docs") {
get {
path("swagger.json") {
getFromResource("swagger.json", ContentTypes.`application/json`)
} ~
(pathEnd | pathSingleSlash) {
redirect("docs/index.html", StatusCodes.TemporaryRedirect)
} ~
getFromResourceDirectory("swagger-ui")
}
}
This serves files (recursively) from the directory ./web/
package com.softwaremill.spray.server
import akka.actor.ActorSystem
import spray.routing.SimpleRoutingApp
object Step1Complete extends App with SimpleRoutingApp {
implicit val actorSystem = ActorSystem()
startServer(interface = "localhost", port = 3300) {
get {
path("hello") {
complete {
"Welcome to Amber Gold!"
}
}
} ~
pathPrefix("web" ) {
getFromDirectory("./web/")
}
}
}

When does Play load application.conf?

Is application.conf already loaded when the code in Global.scala is executed? I'm asking because I've tried to read some configuration items from Global.scala and I always get None. Is there any workaround?
In Java it's available beforeStart(Application app) already
public class Global extends GlobalSettings {
public void beforeStart(Application app) {
String secret = Play.application().configuration().getString("application.secret");
play.Logger.debug("Before start secret is: " + secret);
super.beforeStart(app);
}
}
As it's required to i.e. configuring DB connection, most probably Scala works the same way (can't check)
Here below is how to read the configuration just after it has been loaded but before the application actually starts:
import play.api.{Configuration, Mode}
import play.api.GlobalSettings
import java.io.File
import utils.apidocs.InfoHelper
object Global extends GlobalSettings {
override def onLoadConfig(
config: Configuration,
path: File, classloader:
ClassLoader,
mode: Mode.Mode): Configuration = {
InfoHelper.loadApiInfo(config)
config
}
}
And here below, just for your info, is the source of InfoHelper.loadApiInfo – it just loads API info for Swagger UI:
package utils.apidocs
import play.api.Configuration
import com.wordnik.swagger.config._
import com.wordnik.swagger.model._
object InfoHelper {
def loadApiInfo(config: Configuration) = {
config.getString("application.name").map { appName =>
config.getString("application.domain").map { appDomain =>
config.getString("application.emails.apiteam").map { contact =>
val apiInfo = ApiInfo(
title = s"$appName API",
description = s"""
Fantastic application that makes you smile. You can find our
more about $appName at $appDomain.
""",
termsOfServiceUrl = s"//$appDomain/terms",
contact = contact,
license = s"$appName Subscription and Services Agreement",
licenseUrl = s"//$appDomain/license"
)
ConfigFactory.config.info = Some(apiInfo)
}}}
}
}
I hope it helps.

How to test remote (production) Scalatra web service with Specs2?

I'm using Specs2 to test my Scalatra web service.
class APISpec extends ScalatraSpec {
def is = "Simple test" ^
"invalid key should return status 401" ! root401^
addServlet(new APIServlet(),"/*")
def root401 = get("/payments") {
status must_== 401
}
}
This tests the web service locally (localhost). Now I would like to perform the same tests to the production Jetty server. Ideally, I would be able to do this by only changing some URL. Is this possible at all ? Or do I have to write my own (possible duplicate) testing code for the production server?
I don't know how Scalatra manages its URLs but one thing you can do in specs2 is control parameters from the command-line:
class APISpec extends ScalatraSpec with CommandLineArguments { def is = s2"""
Simple test
invalid key should return status 401 $root401
${addServlet(new APIServlet(),s"$baseUrl/*")}
"""
def baseUrl = {
// assuming that you passed 'url www.production.com' on the command line
val args = arguments.commandLine.split(" ")
args.zip(args.drop(1)).find { case (name, value) if name == "url" => value }.
getOrElse("localhost:8080")
}
def root401 = get(s"$baseUrl/payments") {
status must_== 401
}
}