I want to create controller method and parametrize it with Class parameter to call it in routes:
GET /api/res1 controllers.GenericController.index(clazz:Class = Res1.class)
GET /api/res2 controllers.GenericController.index(clazz:Class = Res2.class)
and during compilation play shouts:
[error] /home/../workspace/repo/prototype/conf/routes:26: identifier expected but 'class' found.
[error] /home/../workspace/repo/prototype/conf/routes:26: ')' expected but '}' found.
why '}' ? and how to make my idea work?
Try changing to this:
/api/res1 controllers.GenericController.index(clazz: Class[_] = classOf[full.package.name.Res1])
Works just fine for me.
Related
This question already has answers here:
Maven archetype - Velocity error because of a colon
(3 answers)
Closed 6 years ago.
I am trying to default some property values in a templated class and it looks like the velocity engine the maven archtype plugin is using is choking on the ':' with errors like:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-archetype-plugin:2.4:generate (default-cli) on project standalone-pom: org.apache.maven.archetype.exception.ArchetypeGenerationFailure: Error merging velocity templates: Encountered ":" at line 18, column 40 of archetype-resources/__modelName__/src/main/java/client/CandyClientConfig.java
[ERROR] Was expecting one of:
[ERROR] "}" ...
[ERROR] <DOT> ...
[ERROR] "(" ...
[ERROR] -> [Help 1]
[ERROR]
I have tried several escape sequences and it complains about them all:
#Value("${candy.http.maxConnections\:100}")
#Value("${candy.http.maxConnections\\:100}")
#Value("${candy.http.maxConnections:100}")
in the top of my archetype pom
#set($colon = ':')
then
#Value("${candy.http.maxConnections$colon100}")
This should be easily to beat. So, what am I missing?
I faced the same issue in the past, the problem lies in the common syntax ${...} used by velocity and the java code.
Though I don't consider it a particularly elegant solution, I solved the problem as follows:
#set( $candy_http_max_connections_decl = '${candy.http.maxConnections:100}')
#Value("${candy_http_max_connections_decl}")
PS. To keep the code readable in case of many of such declarations in my source file, I kept the #set declarations close to their use (in the example, the line immediately above the #Value(...) annotation), instead of putting them at the beginning of the file as I would have normally done
If you address the '$' character instead of ':', like in :
#set( $dollar = '$' )
then
#Value("${dollar}{candy.http.maxConnections:100}")
it seems to work
When I compile my java class. There are some errors of cannot find symble '/' in class name. Below is a sample code from my class:
public TransactionSearchResponse submit(TxnSearchRequest req)
{
url = (new StringBuilder(String.valueOf(req.getBaseUrl()))).append("/txns/search").toString();
method = "POST";
return (TransactionSearchResponse)sendRequest(req, com/COMPPONENT/api/TransactionSearchResponse);
}
Be cause of copyright from author of this code block. sendRequest Method is deleted.
Netbeans cannot recognize the dash '/' in the class name "com/COMPPONENT/api/TxnResp". And the class name contains some parts:
Package name: com.COMPONENT.api
Class name: TxnResp
Java file name: TxnResp.java
The dash '/' show in red color as Netbeans mask it an error line. The only hint I got from Netbeans are "Add import for com.COMPONENT.api.TxnResp" or "Flip Operands of '/' (may alter semantics), and I did that but got no luck. And when I try to run the code, it generate an error of "Cannot find symbol". Can you help me to solve this issue?
Regards,
Dung Tri
If a method sendRequest is declared like
Object sendRequest( Request x, Class<?> y )
you'll have to call it with an instance of a java.lang.Class object:
... = sendRequest( request, com.COMPPONENT.api.TxnResp.class );
Appending .class is the way of obtaining an instance of a certain Class object (not to be confused with an instance of TxnResp which is created using new TxnResp).
Also, given
com.COMPPONENT.api.TxnResp txnResp = new com.COMPPONENT.api.TxnResp();
the expression
txnResp.getClass()
results in an instance of the Class<com.COMPPONENT.api.TxnResp> but of course the .class notation is more convenient for your purpose.
I tried to make the zenTasks tutorial for the play-java framework (I use the current playframework, which is 2.3.2). As it comes to testing and adding fixtures I'm kind of lost!
The docu states that
Edit the conf/test-data.yml file and start to describe a User:
- !!models.User
email: bob#gmail.com
name: Bob
password: secret
...
And I should download a sample (which is in fact a dead link!)
So I tried myself adding more Users like this:
- !!models.User
email: somemail1#example.com
loginName: test1
- !!models.User
email: somemail2#example.com
loginName: test2
If I then try to load it via
Object load = Yaml.load("test-data.yml");
if (load instanceof List){
List list = (List)load;
Ebean.save(list);
} else {
Ebean.save(load);
}
I get the following Exception:
[error] Test ModelsTest.createAndRetrieveUser failed:
java.lang.IllegalArgumentException: This bean is of type [class
java.util.ArrayList] is not enhanced?, took 6.505 sec [error] at
com.avaje.ebeaninternal.server.persist.DefaultPersister.saveRecurse(DefaultPersister.java:270)
[error] at
com.avaje.ebeaninternal.server.persist.DefaultPersister.save(DefaultPersister.java:244)
[error] at
com.avaje.ebeaninternal.server.core.DefaultServer.save(DefaultServer.java:1610)
[error] at
com.avaje.ebeaninternal.server.core.DefaultServer.save(DefaultServer.java:1600)
[error] at com.avaje.ebean.Ebean.save(Ebean.java:453) [error]
at ModelsTest.createAndRetrieveUser(ModelsTest.java:18) [error]
...
How Am I supposed to load more than one User (or whatever object I wish) and parse them without exception?
In Ebean class save method is overloaded.
save(Object) - expects parameter which is entity (extends Model, has #Entity annotation)
save(Collection) - expects collection of entities.
Yaml.load function returns objecs which can be:
Entity
List of entities
But if we simply do:
Object load = Yaml.load("test-data.yml");
Ebean.save(load);
then save(Object) method will be called. This is because at compile time compiler doesn't know what exactly will Yaml.load return. So above code will throw exception posted is question when there is more then one user in "test-data.yml" file.
But when we cast the result to List as in code provided by OP then everything works good. save(Collection) method is called and all entities are saved correctly. So the code from question is correct.
I have same problem with loading data from "test-data.yml". But I have found solution for this problem. Here is http://kewool.com/2013/07/bugs-in-play-framework-version-2-1-1-tutorial-fixtures/ solution code. But all Ebean.save methods must be replaced with Ebean.saveAll methods.
I use playframework2.2: try to build a play support project.
in my Build.scala, I want to add play.Project.playJavaSetting:
val main = play.Project(appName, appVersion, appDependencies)
.settings(play.Project.playJavaSettings) //error here
.settings(
resolvers += "webjars" at "http://webjars.github.com/m2",
resolvers += "typesafe" at "http://repo.typesafe.com/typesafe/release"
)
the error is:
[error] F:\git\play-example-form\project\Build.scala:19: overloaded method value
settings with alternatives:
[error] (ss: sbt.Def.Setting[_]*)sbt.Project <and>
[error] => Seq[sbt.Def.Setting[_]]
[error] cannot be applied to (Seq[sbt.Setting[_]])
[error] .settings(play.Project.playJavaSettings)
[error] ^
If I do not add playJavaSetting, it give me error about wrong collection apply, I mean:
val main = play.Project(appName, appVersion, appDependencies)
//.settings(play.Project.playJavaSettings)
and the error is:
[error] required: play.api.data.Form<StudentFormData>,scala.collection.immutab
le.Map<String,Object>,scala.collection.immutable.List<String>,scala.collection.i
mmutable.Map<String,Object>,scala.collection.immutable.Map<String,Object>
[error] found: play.data.Form<StudentFormData>,java.util.Map<String,Boolean>,j
ava.util.List<String>,java.util.Map<String,Boolean>,java.util.Map<String,Boolean
you can see the framework apply the scala.collection.immutable.List instead of play.util.List, If I really want to apply the java collections how to set the environment setting in Build.scala file?
You should change
.settings(play.Project.playJavaSettings)
to
.settings(play.Project.playJavaSettings: _*)
The settings method is declared as def settings(ss: Setting[_]*), which means it takes repeated parameters of type Setting[_]. The play.Project.playJavaSettings is of type Seq[Setting[_]]. To convert one to another Scala has a special type annotation.
If you are interested in details check 4.6.2 Repeated Parameters of The Scala Language Specification
I saw a few questions about this topic, but none answer the part I am stuck on. By the way, based on the issues people are running into, I might suggest giving a default java implementation of the TemplatesPlugin after all.
The problem I have, is that I copied the two needed views from SecureSocial to my views folder, and changed the RequestHeader as others have noted to: play.api.mvc.RequestHeader and now I am getting:
ambiguous implicit values: both method requestHeader in object PlayMagicForJava of type => play.api.mvc.RequestHeader and value request of type play.api.mvc.RequestHeader match expected type play.api.mvc.RequestHeader
Version: Play-2.1.1, Java 7, SecureSocial from Master.
EDIT:
Play Compile:
[error] C:\Java\AwsConsole\app\views\secure\login.scala.html:41: ambiguous impli
cit values:
[error] both method requestHeader in object PlayMagicForJava of type => play.ap
i.mvc.RequestHeader
[error] and value request of type play.api.mvc.RequestHeader
[error] match expected type play.api.mvc.RequestHeader
[error] #provider(p.id)
[error] ^
[error] C:\Java\AwsConsole\app\views\secure\provider.scala.html:20: ambiguous im
plicit values:
[error] both method requestHeader in object PlayMagicForJava of type => play.ap
i.mvc.RequestHeader
[error] and value request of type play.api.mvc.RequestHeader
[error] match expected type play.api.mvc.RequestHeader
[error] <form action = "#securesocial.core.providers.utils.Route
sHelper.authenticateByPost("userpass").absoluteURL(IdentityProvider.sslEnabled)"
[error]
^
[error] two errors found
[error] (compile:compile) Compilation failed
Browsing after Play Run instead:
Internal server error, for (GET) [/] ->
sbt.PlayExceptions$CompilationException: Compilation error[ambiguous implicit va
lues:
both method requestHeader in object PlayMagicForJava of type => play.api.mvc.Re
questHeader
and value request of type play.api.mvc.RequestHeader
match expected type play.api.mvc.RequestHeader]
at sbt.PlayReloader$$anon$2$$anonfun$reload$2$$anonfun$apply$15$$anonfun
$apply$16.apply(PlayReloader.scala:349) ~[na:na]
at sbt.PlayReloader$$anon$2$$anonfun$reload$2$$anonfun$apply$15$$anonfun
$apply$16.apply(PlayReloader.scala:349) ~[na:na]
at scala.Option.map(Option.scala:133) ~[scala-library.jar:na]
at sbt.PlayReloader$$anon$2$$anonfun$reload$2$$anonfun$apply$15.apply(Pl
ayReloader.scala:349) ~[na:na]
at sbt.PlayReloader$$anon$2$$anonfun$reload$2$$anonfun$apply$15.apply(Pl
ayReloader.scala:346) ~[na:na]
at scala.Option.map(Option.scala:133) ~[scala-library.jar:na]
The request must be passed explicitely to the login template, the login template must pass the request explicitely to the provider template and the provider template must specify the request when invoking RoutesHelper.authenticateByPost("userpass").absoluteURL. More detailed:
The java TemplatesPlugin should have this getLoginPage implementation:
#Override
public <A> Html getLoginPage(final play.api.mvc.Request<A> request, final Form<Tuple2<String, String>> form,
final Option<String> msg) {
return views.html.login.render(request, form, msg);
}
The parameters (first line) of login.scala.html should look like this:
#(request: play.api.mvc.RequestHeader, loginForm: play.api.data.Form[(String,String)], errorMsg: Option[String] = None)
Change calls from login.scala.html to the provider template to pass the request explicitely (we'll adjust its parameters in the next step).
login.scala.html line 41, change
#provider(p.id)
to
#provider(request, p.id)
login.scala.html line 55, change
#provider("userpass", Some(loginForm))
to
#provider(request, "userpass", Some(loginForm))
The parameters (first line) of provider.scala.html should take the request as first, explicit parameter:
#(request: play.api.mvc.RequestHeader, providerId: String, loginForm: Option[play.api.data.Form[(String, String)]] = None)
Line 20 of the provider template needs to pass the request (so that the correct method is invoked, otherwise you'll get a RuntimeException: There is no HTTP Context available from here):
<form action = "#securesocial.core.providers.utils.RoutesHelper.authenticateByPost("userpass").absoluteURL(IdentityProvider.sslEnabled)(request)"
This should be all needed changes, if you're using other templates they would have to be adjusted accordingly.
Just to mentiond it: I had changed our java TemplatesPlugin to a scala version (to have it more straight forward).