How is path interpreted when using SIRD in Play framework - playframework-2.3

The following example is from Play's documentation
To use the routing DSL in conjunction with a regular Play project that uses a routes file and controllers, extend the SimpleRouter:
package api
import javax.inject.Inject
import play.api.mvc._
import play.api.routing.Router.Routes
import play.api.routing.SimpleRouter
import play.api.routing.sird._
class ApiRouter #Inject()(controller: ApiController)
extends SimpleRouter
{
override def routes: Routes = {
case GET(p"/") => controller.index
}
}
Add the following line to conf/routes:
-> /api api.ApiRouter
Question - In the above example As /api already maps to ApiRouter, does GET(p"/") resolve to somedomain.com/api/ or somedomain.com/

It will resolve to somedomain.com/api/, that is the main idea of the SIRD - it allows you to modularize routers.

Related

Field personRepositary in () required a bean of type () that could not be found

I am trying to run a spring developed web app and I'm getting the following error.
My folder structure is as follows.
Here is my PersonRepositary.java code which is inside the repositary folder.
package com.travelx.travelx.repositary;
import org.springframework.data.repository.CrudRepository;
import com.travelx.travelx.models.Person;
public interface PersonRepositary extends CrudRepository<Person, Integer> {
}
The RegisterController.java file which is in the controllers folder is ac follows.
package com.travelx.travelx.controllers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.travelx.travelx.models.Person;
import com.travelx.travelx.repositary.PersonRepositary;
#RestController
#RequestMapping("register")
public class RegisterController {
#Autowired
private PersonRepositary personRepositary;
#PostMapping("login")
public String registerPerson(#RequestBody Person person) {
personRepositary.save(person);
return "You are Registered!";
}
}
And the TravelXApplication.java file which is in the controllers is below.
package com.travelx.travelx.controllers;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
#SpringBootApplication
#ComponentScan
#EntityScan
#EnableJpaRepositories
public class TravelxApplication {
public static void main(String[] args) {
SpringApplication.run(TravelxApplication.class, args);
}
}
I'm trying to make a web page where a person can register to a site. Here, I'm using xampp as my platform to handle the back end. As shown in the image, the controllers, repositories and and models are implemented in separate folders. I'm new to Spring. So no matter how hard I to find what the problem is, I cant seem to find it. Can some one help me please?
--------------UPDATE------------------
I've moved my TravelXApplication.java to the com.travelx.travelx and now this error is gone.Spring works fine. However when I open my form, insert data and try to save it, the browser gives me the following error.
How do I solve it?
Your PersonRepositary is not registered as a bean in your Spring context. In practice, this means that Spring is not be able to inject it in your RegisterController.
I suspect that #EnableJpaRepositories, #EntityScan and #ComponentScan are unnecessary in your main application class and are actually causing Spring automatic configuration to be overridden. Try deleting these three annotations from TravelxApplication.
Here's the answer to why it should still work without annotations.
Update: just noticed that your TravelxApplication is located in the controllers package, but then it won't have visibility to your repository. Make sure to move your main class to the com.travelx.travelx package.

No instance of play.api.libs.json.Format is available for scala.Iterable[java.lang.String]

Trying to map a simple class using play version 2.6.2 and scala 2.11.11
import play.api.libs.json._
import play.api.libs.json.util._
import play.api.libs.json.Reads._
import play.api.libs.json.Writes._
import play.api.libs.json.Format._
import play.api.libs.functional.syntax._
case class ObjectInfo (
names : Iterable[String],
info : Iterable[String]
)
object ObjectInfo {
/**
* Mapping to and from JSON.
*/
implicit val documentFormatter = Json.format[ObjectInfo]
}
getting:
No instance of play.api.libs.json.Format is available for
scala.Iterable[java.lang.String], scala.Iterable[java.lang.String] in
the implicit scope (Hint: if declared in the same file, make sure it's
declared before)
I was expecting Play to automatically map these fields since they're not complex object types but simple Collection of strings.
You provide "too much" implicit stuff with your imports. If you remove all imports but the first one, it will compile and do what you want.
If you enable implicit parameter logging via the scalac option -Xlog-implicits, you will see various "ambigouity" and "diverging implicit expansion" errors. The conflicting imports are import play.api.libs.json.Reads._/import play.api.libs.json.Writes._ and import play.api.libs.json.Format._. Maybe someone else can explain this conflict in more detail.

How to troubleshoot es6 module dependencies?

I am developing a React & Reflux app, which is bundled by webpack with babel-loader (v6), and I am experiencing es6 modules dependencies issues
For example, I have a component that use the reflux .connect() mixin :
import MyStore from '../stores/my-store';
const Component = React.createClass({
mixins: [Reflux.connect(MyStore)]
});
When I import all modules individually in each file like this, everything's fine.
I then tried to improve my code by using deconstructed import statements :
...in a component :
//import One from '../js/one';
//import Two from '../js/two';
//import Three from '../js/three';
import { One, Two, Three } from '../js'; // Instead
...and in js/index.js :
import One from './one';
import Two from './two';
import Three from './three';
export { One, Two, Three };
App source code files are more concise using the above technique, because I can import all components in one import line.
But when I use this, some dependencies end up beeing undefined when I use them
If I use the same updated example...
//import MyStore from '../stores/my-store';
import { MyStore } from '../stores'; // Instead
const Component = React.createClass({
mixins: [Reflux.connect(MyStore)]
});
...MyStore parameter ends up undefined in Reflux.connect method.
I tried to troubleshoot in the debugger, but I'm not really aware of what's going on with the __webpack_require__(xxx) statements in the generated bundle. There must be a circular dependency that babel-loader or webpack require could not figure out when there are the index.js files re-exporting individual modules.
Do you know any tool that can help me figure this out? I tried madge but it does not work with es6 modules, and I could not find anything that would tell me where anything is wrong
In order to get extended info about build, run:
webpack --profile --display-modules --display-reasons
It will give you bunch of information for optimisation/profiling.
import statement is used to import functions, objects or primitives that have been exported from an external module.
As per MDN doc, you can import the Modules not the directory.
import name from "module-name";
import * as name from "module-name";
import { member } from "module-name";
import { member as alias } from "module-name";
import { member1 , member2 } from "module-name";
import { member1 , member2 as alias2 , [...] } from "module-name";
import defaultMember, { member [ , [...] ] } from "module-name";
import defaultMember, * as alias from "module-name";
import defaultMember from "module-name";
import "module-name";
Reference URL:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
http://es6-features.org/#ValueExportImport
https://github.com/lukehoban/es6features#modules
http://www.2ality.com/2014/09/es6-modules-final.html
As a workaround keep one file as base.js and include all your 3 files.

How to insert json fixture data in Play Specification tests?

I have a Scala Play 2.2.2 application and as part of my Specification tests I would like to insert some fixture data for testing preferably in json format. For the tests I use the usual in-memory H2 database. How can I accomplish this? I have searched all the documentation but there is no mention to this anywhere.
Note that I would prefer not to build my own flavor of fixture implementation via the Global. There should be a non-hacky way to this right?
AFAIK there is no built-in stuff to do this, ala Rails, and it's hard to imagine what the devs could do without making Play Scala much more opinionated about the way persistence should be handled (which I'd personally consider a negative.)
I also use H2 for testing and employ plain SQL fixtures in a resource file and load them before tests using a couple of (fairly simple) helpers:
package object helpers {
import java.io.File
import java.sql.CallableStatement
import org.specs2.execute.{Result, AsResult}
import org.specs2.mutable.Around
import org.specs2.specification.Scope
import play.api.db.DB
import play.api.test.FakeApplication
import play.api.test.Helpers._
/**
* Load a file containing SQL statements into the DB.
*/
private def loadSqlResource(resource: String)(implicit app: FakeApplication) = DB.withConnection { conn =>
val file = new File(getClass.getClassLoader.getResource(resource).toURI)
val path = file.getAbsolutePath
val statement: CallableStatement = conn.prepareCall(s"RUNSCRIPT FROM '$path'")
statement.execute()
conn.commit()
}
/**
* Run a spec after loading the given resource name as SQL fixtures.
*/
abstract class WithSqlFixtures(val resource: String, val app: FakeApplication = FakeApplication()) extends Around with Scope {
implicit def implicitApp = app
override def around[T: AsResult](t: => T): Result = {
running(app) {
loadSqlResource(resource)
AsResult.effectively(t)
}
}
}
}
Then, in your actual spec you can do something like so:
package models
import helpers.WithSqlFixtures
import play.api.test.PlaySpecification
class MyModelSpec extends PlaySpecification {
"My model" should {
"locate items correctly" in new WithSqlFixtures("model-fixtures.sql") {
MyModel.findAll().size must beGreaterThan(0)
}
}
}
Note: this specs2 stuff could probably be better.
Obviously if you really need JSON you'll have to add extra machinery to deserialise your models and persist them in the database (often in your app you'll be doing these things anyway, in which case that might be relatively trivial.)
You'll also need:
Some evolutions to establish your DB schema in conf/evolutions/default
The evolution plugin enabled, which will build your schema when the FakeApplication starts up
The appropriate H2 DB config

Serializing and unserializing case classes with lift-json

I'm attempting basic serialization/hydration with lift-json, but without success. As near as I can tell from the package readme, this should work. Help?
I'm using Scala 2.8.0 and Lift 2.2 cross-built for 2.8 with sbt ("net.liftweb" %% "lift-json" % "2.2").
import net.liftweb.json._
import net.liftweb.json.Serialization.{read, write}
implicit val formats = Serialization.formats(NoTypeHints)
case class Route(title: String)
val rt = new Route("x277a1")
val ser = write(rt)
// ser: String = {} ...
val deser = read[Route]("""{"title":"Some Title"}""")
// net.liftweb.json.MappingException: Parsed JSON values do not match with class constructor
Lift JSON's serialization does not work for case classes defined in REPL (paranamer can't find the bytecode to read the type metadata). Compile Route with scalac and then the above example works.
The same problem applies every time when the (de)serialuzed class is not on the classpath. In such case, paranamer can't read the parameter names. It is necessary to provide a custom ParameterNameReader.
Such problem applies for e.g.:
REPL (as mentioned) - unless you define the class outside the REPL and add via classpath.
Play Framework - unless you provide a simple custom ParameterNameReader (see below) or load the (de)serialized class as a Maven/Play/... dependency
Feel free to add another situation (you can edit this post).
The PlayParameterNameReader:
import net.liftweb.json.ParameterNameReader
import java.lang.reflect.Constructor
import play.classloading.enhancers.LocalvariablesNamesEnhancer
import scala.collection.JavaConversions._
object PlayParameterReader extends ParameterNameReader{
def lookupParameterNames(constructor: Constructor[_]) = LocalvariablesNamesEnhancer.lookupParameterNames(constructor)
}