Im currently using Grails 4 for a RESTfull App.
Have the following controller, a custom one that throws a json response:
package nslbv_siu
import grails.rest.*
import grails.converters.*
class LoginController
{
static allowedMethods = [ login:'POST' ]
static responseFormats = [ 'json', 'xml' ]
static defaultAction = "login"
def login()
{
if( params.user == '' )
{
render "{ 'succes':false, 'error':'Ingrese su usuario.' }"
}
if( params.pass == '' )
{
render "{ 'success':false, 'error':'Ingrese su contraseña.' }"
}
def attempted_user = User.queryUserByUsernameAndActive( params.user, true )
if( attempted_user )
{
if ( attempted_user.pass == params.pass.md5() )
{
render "{ 'success':true, 'error':'', " +
"'user':'" + attempted_user.user + "', " +
"'mail':'" + attempted_user.dni + "', " +
"'apenom':'" + attempted_user.apenom + "', " +
"'profile_pic':'" + attempted_user.profile_pic + "' }"
}
else
{
render "{ 'success':false, 'error':'Usuario o Contraseña incorrectos' }"
}
}
else
{
render "{ 'success':false, 'error':'Usuario o Contraseña incorrectos' }"
}
}
User queryUserByUsernameAndActive(String username, Boolean active)
{
User.all.find
{
it.user == username && it.active == active
}
}
}
Need to call http://localhost:8080/login?user=myuser&pass=mypass
But throws 404 not found, dont know why!, must I use another convention to make my routes be published?
My mappings:
package nslbv_siu
class UrlMappings {
static mappings =
{
delete "/$controller/$id(.$format)?"(action:"delete")
get "/$controller(.$format)?"(action:"index")
get "/$controller/$id(.$format)?"(action:"show")
post "/$controller(.$format)?"(action:"save")
put "/$controller/$id(.$format)?"(action:"update")
patch "/$controller/$id(.$format)?"(action:"patch")
"/"(controller: 'application', action:'index')
"500"(view: '/error')
"404"(view: '/notFound')
"/login"(controller: "LoginController", action: "login") -->does not seem to work
}
}
I dont understand why it does not work!, am I doing something wrong?
grails url-mappings-report throws the following
Dynamic Mappings
| * | ERROR: 404 | View: /notFound |
| * | ERROR: 500 | View: /error |
Controller: LoginController
| POST | /login | Action: login |
Controller: application
| * | / | Action: index |
It was:
"/login"(controller: "login", action: "login")
instead of
"/login"(controller: "LoginController", action: "login")
Related
Is my first time using jflex, I'm following a tutorial i found on the internet in my native language (portuguese), I installed and assembled everything.
But when I try to generate the "Lexer" class, it shows a syntax error in my ".flex" file, I don't know what might be happening because it all seems to be ok.
.flex file
//NOME_VARIAVEL,INT,DEC,COMENTARIO,BRANCO,PALAVRA_CHAVE,ERRO
package Compilador;
import static Compilador.Token.*;
%%
%{
private void imprimir (String token,String lexema){
System.out.println(lexema +" ===>> " + token);
}
%}
%class Lexer
%type Token
nomeVariavel = [_a-zA-Z][_zA-z0-9]*
inteiro = [0-9]+
decimal = [0-9]+["."]+[0-9]+
blocoComentario = "/*" ~"*/"
branco = [\t|\n|\r]+
linhaComentario = [branco]*"//" .*
palavrasChave = "if" | "class" | "int" | "while" | "for" | "do" | "float"
%%
{palavrasChave} { imprimir("PALAVRA_CHAVE : ", yytext()); return PALAVRA_CHAVE; }
{nomeVariavel} { imprimir("VARIAVEL : ", yytext()); return NOME_VARIAVEL; }
{inteiro} { imprimir("NUMERO INTEIRO : ", yytext()); return INT; }
{decimal} { imprimir("NUMERO DECIMAL : ", yytext()); return DEC; }
{blocoComentario} { imprimir("COMENTARIO : ", yytext()); return COMENTARIO; }
{linhaComentario} { imprimir("COMENTARIO : ", yytext()); return COMENTARIO; }
{branco} ( return BRANCO; }
. {imprimir("<<< CARACTER INVALIDO!!! >>> ",yytext()); return ERROR;}
<<EOF>> {return null;}
Token.java file
package compilador;
public enum Token{
NOME_VARIAVEL, INT, DEC, COMENTARIO, BRANCO, PALAVRA_CHAVE, ERROR;
}
generator.flex file
package compilador;
import java.io.*;
public class GeraLexer {
public static void main(String[] args) throws IOException {
String arquivo ="<path redacted for reasons, but it is finding the file>";
geraLexer(arquivo);
}
public static void geraLexer(String arq){
File file = new File(arq);
jflex.Main.generate(file);
}
}
error presented when generating
Reading "<path redacted for reasons, but it is finding the file>"
Error in file "<path redacted for reasons, but it is finding the file>" (line 28):
Syntax error.
. {imprimir("<<< CARACTER INVALIDO!!! >>> ",yytext()); return ERROR;}
^
Exception in thread "main" jflex.GeneratorException: Generation aborted
at jflex.Main.generate(Main.java:139)
at compilador.GeraLexer.geraLexer(GeraLexer.java:13)
at compilador.GeraLexer.main(GeraLexer.java:8)
Java Result: 1
CONSTRUÍDO COM SUCESSO (tempo total: 0 segundos)
Appreciate anyone willing to help, yes, I googled first.
In the previous line, you have
{branco} ( return BRANCO; }
The ( should be a {.
As you will discover soon writing your own parser, it is not always easy to notice an error in the right place. The error is often detected one token later than you might want, and sometimes that token is on the next line.
package com.fhjony.ocbt
import grails.web.servlet.mvc.GrailsParameterMap
class MemberService {
def save(GrailsParameterMap params) {
Member member = new Member(params)
def response = AppUtil.saveResponse(false, member)
if (member.validate()) {
member.save(true)
if (!member.hasErrors()){
response.isSuccess = true
}
}
return response
}
def update(Member member, GrailsParameterMap params) {
member.properties = params
def response = AppUtil.saveResponse(false, member)
if (member.validate()) {
member.save(flush: true)
if (!member.hasErrors()){
response.isSuccess = true
}
}
return response
}
def getById(Serializable id) {
return Member.get(id)
}
def list(GrailsParameterMap params) {
params.max = params.max ?: GlobalConfig.itemPerPage()
List<Member> memberList = Member.createCriteria().list(params) {
if (params?.colName && params?.colValue) {
like(params.colName, "%" + params.colValue + "%")
}
if (!params.sort) {
order("id", "desc")
}
}
return [list: memberList, count: memberList.totalCount]
}
def delete(Member member) {
try {
member.delete(flush: true,failOnError:true)
} catch (Exception e) {
println(e.getMessage())
return false
}
return true
}
}
Error message:
URI /member/update Class
javax.persistence.TransactionRequiredException Message null Caused by
no transaction is in progress
Line | Method
->> 211 | invoke in org.grails.core.DefaultGrailsControllerClass$ReflectionInvoker
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | 188 | invoke in org.grails.core.DefaultGrailsControllerClass | 90 | handle . . . .
. in org.grails.web.mapping.mvc.UrlMappingsInfoHandlerAdapter | 1039
| doDispatch in
org.springframework.web.servlet.DispatcherServlet | 942 | doService
. . . in '' | 1005 | processRequest in
org.springframework.web.servlet.FrameworkServlet | 908 | doPost . .
. . . in '' | 882 | service in '' | 77 |
doFilterInternal in
You want your database interactions to be happening in a transactional context. One simple piece of that is you can mark your service class with #grails.gorm.transactions.Transactional.
Separate from that, and this isn't really related to your question, but passing GrailsParameterMap map around as a method argument is an unusual thing to do. What the right thing to do is depends on some factors in your app and you may want to pass values into your service rather than the whole map but if you really want the whole map in the service, one way to get there is by way of WebAttributes.
import grails.gorm.transactions.Transactional
import grails.web.api.WebAttributes
#Transactional
class MemberService implements WebAttributes {
def serviceMethod() {
// you can access params here because
// WebAttributes provides access to it
Member member = new Member(params)
// ...
}
}
I am new in Play Framework and need some advice.
In my project I send AJAX request but unfortunatly Play Framework raise error which you can see below. From error message you can notice that problem most likely in controller. Where was my mistake? How to fix this error?
[error] application -
! #79mg8k016 - Internal server error, for (GET) [/] ->
play.api.UnexpectedException: Unexpected exception[CreationException: Unable to create injector, see the following errors:
1) No implementation for play.api.db.Database was bound.
while locating play.api.db.Database
for the 1st parameter of controllers.GetValuesController.<init>(GetValuesController.scala:14)
while locating controllers.GetValuesController
for the 4th parameter of router.Routes.<init>(Routes.scala:33)
at play.api.inject.RoutesProvider$.bindingsFromConfiguration(BuiltinModule.scala:121):
Binding(class router.Routes to self) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1)
1 error]
at play.core.server.DevServerStart$$anon$1.reload(DevServerStart.scala:186)
at play.core.server.DevServerStart$$anon$1.get(DevServerStart.scala:124)
at play.core.server.AkkaHttpServer.handleRequest(AkkaHttpServer.scala:241)
at play.core.server.AkkaHttpServer.$anonfun$createServerBinding$1(AkkaHttpServer.scala:138)
at akka.stream.impl.fusing.MapAsyncUnordered$$anon$26.onPush(Ops.scala:1304)
at akka.stream.impl.fusing.GraphInterpreter.processPush(GraphInterpreter.scala:519)
at akka.stream.impl.fusing.GraphInterpreter.processEvent(GraphInterpreter.scala:482)
at akka.stream.impl.fusing.GraphInterpreter.execute(GraphInterpreter.scala:378)
at akka.stream.impl.fusing.GraphInterpreterShell.runBatch(ActorGraphInterpreter.scala:588)
at akka.stream.impl.fusing.GraphInterpreterShell$AsyncInput.execute(ActorGraphInterpreter.scala:472)
Caused by: com.google.inject.CreationException: Unable to create injector, see the following errors:
1) No implementation for play.api.db.Database was bound.
while locating play.api.db.Database
for the 1st parameter of controllers.GetValuesController.<init>(GetValuesController.scala:14)
while locating controllers.GetValuesController
for the 4th parameter of router.Routes.<init>(Routes.scala:33)
at play.api.inject.RoutesProvider$.bindingsFromConfiguration(BuiltinModule.scala:121):
Binding(class router.Routes to self) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1)
It seems like something wrong in controller. Where is my mistake, how to fix it?
I use:
JDK 1.8.0_181
SBT 0.13.5
Scala 2.12
Play Framework 2.6.20
routes:
GET /get_values controllers.GetValuesController.get_data_from_db(start_date_time:String, end_date_time:String, city_name:String)
GetValuesController.scala:
package controllers
import javax.inject._
import akka.actor.ActorSystem
import play.api.Configuration
import play.api.mvc.{AbstractController, ControllerComponents}
import play.api.libs.ws._
import scala.concurrent.duration._
import scala.concurrent.{ExecutionContext, Future, Promise}
import services._
import play.api.db.Database
class GetValuesController#Inject()(db: Database, conf: Configuration, ws: WSClient, cc: ControllerComponents, actorSystem: ActorSystem)(implicit exec: ExecutionContext) extends AbstractController(cc) {
def get_data_from_db(start_date_time: String, end_date_time: String, city_name: String) = Action.async {
getValue(1.second, start_date_time: String, end_date_time: String, city_name: String).map {
message => Ok(message)
}
}
private def getValue(delayTime: FiniteDuration, start_date_time: String, end_date_time: String, city_name: String): Future[String] = {
val promise: Promise[String] = Promise[String]()
val service: GetValuesService = new GetValuesService(db)
actorSystem.scheduler.scheduleOnce(delayTime) {
promise.success(service.get_values(start_date_time, end_date_time, city_name))
}(actorSystem.dispatcher)
promise.future
}
}
GetValuesService.scala:
package services
import play.api.db.Database
import play.api.libs.json._
class GetYoutubeSpeedValuesService(db: Database) {
def get_youtube_speed_values(start_date_time: String, end_date_time: String, city_name: String): String ={
val SQL_STATEMENT = "SELECT " +
"table_name.\"Stamper\" AS DATE_TIME, " +
"table_name.\"CITY\" AS CITY, " +
"MAX(table_name.avg) AS MAX_SPEED " +
"FROM table_name" +
"WHERE table_name.\"CITY\"='" + city_name + "' " +
"AND (table_name.\"Stamper\" BETWEEN '" + start_date_time + "' AND '" + end_date_time + "') " +
"GROUP BY table_name.\"Stamper\", table_name.\"CITY\";"
val connection = db.getConnection()
var json_array = Json.arr()
try {
val query = connection.createStatement.executeQuery(SQL_STATEMENT)
while (query.next()) {
val json_object = Json.obj(
"DATE_TIME" -> query.getString(1),
"CITY" -> query.getString(2),
"MAX_SPEED" -> query.getString(3)
)
json_array +:= json_object
}
} finally {
connection.close()
}
println(json_array)
json_array.toString()
}
}
application.conf:
db.postgres.driver=org.postgresql.Driver
db.postgres.url="jdbc:postgresql://host:port/database_name"
db.postgres.username = "username"
db.postgres.password = "password"
Javascript:
$.ajax({
type: "POST",
url: "http://localhost:9000/get_values",
data: {
start_date_time: '2018-10-01 00:00:00',
end_date_time: '2018-10-31 23:00:00',
city_name: 'London'
},
success: function (result) {
console.log(result);
},
error: function (jqXHR, textStatus, errorThrown) {
console.log("jqXHR: " + jqXHR);
console.log("textStatus: " + textStatus);
console.log("errorThrown: " + errorThrown);
}
});
ERROR:
Action Not Found
For request 'POST /get_values'
In the same time controller works now correctly! If I call lets say such url: http://localhost:9000/get_values?start_date_time=2018-10-01%2000:00:00&end_date_time=2018-10-31%2023:00:00&city_name=London it return me JSON data.
Well, finally we found the problem. The problem was in application.conf file. In my case I used next database configuration:
db.default.driver=org.postgresql.Driver
db.default.url="jdbc:postgresql://host:port/database_name"
db.default.username = "username"
db.default.password = "password"
Also in AJAX code I remove this part: type: "POST"
I am using grails where authetication is done by Spring Security.I need to unlock User's account before login
#Transactional(readOnly=true, noRollbackFor=[IllegalArgumentException, UsernameNotFoundException])
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = User.findByUsername(username)
// Check and unlock account if 24 Hrs has been passed
userService.checkAndUnlockAccountAfter24Hrs(user.id);
if (!user) throw new NoStackUsernameNotFoundException()
def roles = user.authorities
// or if you are using role groups:
// def roles = user.authorities.collect { it.authorities }.flatten().unique()
def authorities = roles.collect {
new SimpleGrantedAuthority(it.authority)
}
return new MyUserDetails(user.username, user.password, user.enabled,
!user.accountExpired, !user.passwordExpired,
!user.accountLocked, authorities ?: NO_ROLES, user.id,
user.name)
}
Now when I do login with Remember Me check, Then It shows error:
-
| Error 2017-04-18 12:24:40,426 [http-bio-8080-exec-3] ERROR
[/].[default] - Servlet.service() for servlet [default] in context
with path [] threw exception
Message: retrieveUser returned null - a violation of the interface contract
Line | Method
->> 76 | attemptAuthentication in grails.plugin.springsecurity.web.authentication.RequestHolderAuthenticationFilter
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 49 | doFilter in ''
| 82 | doFilter . . . . . . in grails.plugin.springsecurity.web.authentication.logout.MutableLogoutFilter
| 100 | doFilter in com.brandseye.cors.CorsFilter
| 1145 | runWorker . . . . . . in java.util.concurrent.ThreadPoolExecutor
| 615 | run in java.util.concurrent.ThreadPoolExecutor$Worker
^ 744 | run . . . . . . . . . in java.lang.Thread
You have three options:
Comment out that code in boostrap in every run; except first time.
Drop database and create database for every single run
Hacky way:
Use condition(ternary operator) like this:
def adminRole = Role.findByAuthority('ROLE_ADMIN') ? : new Role(authority: 'ROLE_ADMIN').save(flush: true)
def userRole = Role.findByAuthority('ROLE_USER') ? : new Role(authority: 'ROLE_USER').save(flush: true)
def adminUser = User.findByUsername('admin') ? : new User(username: 'admin', password: 'admin', enabled: true).save(flush: true)
def user = User.findByUsername('user') ? : new User(username: 'user', password: 'user', enabled: true).save(flush: true)
if (!adminUser.authorities.contains('ROLE_ADMIN')) {
UserRole.create(adminUser, adminRole)
}
if (!user.authorities.contains('ROLE_USER')) {
UserRole.create(user, userRole)
}
I have a jpql query instanciates a java object in select clause
public List<ChampEtatOT> getEtatOT(Date dateDebut, Date dateFin) {
Query query = em.createQuery("SELECT NEW ChampEtatOT( ot.numero, uo.denominationFr, ot.etat, ot.dateDebutReelle , ot.dateFinReelle, :dateParam1, :dateParam2, :dateParam3) FROM ordre ot JOIN ot.unite uo")
.setParameter("dateParam1", dateDebut, TemporalType.DATE)
.setParameter("dateParam2", dateFin, TemporalType.DATE)
.setParameter("dateParam3", new Date("2015-01-01"), TemporalType.DATE);
return query.getResultList();
}
I put 3 parameters, so i can pass it in the constructor
I get this error
Caused by: Exception [EclipseLink-6137] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.QueryExceptionException Description: An Exception was thrown while executing a ReportQuery with a constructor expression: java.lang.NoSuchMethodException: dz.elit.gmao.commun.reporting.classe.ChampEtatOT.<init>(java.lang.String, java.lang.String, java.lang.String, java.util.Date, java.util.Date)Query: ReportQuery(referenceClass=TravOrdreTravail jpql="SELECT NEW dz.elit.gmao.commun.reporting.classe.ChampEtatOT( ot.numero, uo.denominationFr, ot.etat, ot.dateDebutReelle , ot.dateFinReelle, :dateParam1, :dateParam2, :dateParam3) FROM TravOrdreTravail ot JOIN ot.uniteOrganisationnellle uo")
I think that it's not possible to put parameters in a select clause so does anyone have an idea, the constructor method is as follows:
public ChampEtatOT(String numero, String denominationFr, String etat, Date dateDebutReelle, Date dateFinReelle, Date dateParam1, Date dateParam2, Date dateParam3) {
this.numero = numero;
this.denominationFr = denominationFr;
if (etat.equals("OUV")) {
if (dateDebutReelle.before(dateParam1)) {
etatEntreeSortie = "En instance debut du mois";
} else {
if (dateDebutReelle.before(dateParam2)) {
etatEntreeSortie = "En instance fin du mois";
} else {
if (dateDebutReelle.after(dateParam1) && dateDebutReelle.before(dateParam2)) {
etatEntreeSortie = "Entree/Mois";
}
}
}
}
}
Problem solved, as you suggested bRIMOs Bor it's not possible to pass parameters in a SELECT clause, so i have retreived all the results in a List than filtered the results according to the three dates date1, date2, date3
Query query = em.createQuery("SELECT NEW ChampEtatAteliers"
+ "( ot.numero, uo.denominationFr, ot.etat, ot.dateDebutReelle, ot.dateFinReelle) "
+ "FROM ordre ot JOIN ot.unite uo");
List<ChampEtatAteliers> champEtatAtelierses = query.getResultList();
for (ChampEtatAteliers champEtatAtelierse : champEtatAtelierses) {
if (champEtatAtelierse.getDateDebutReelle().compareTo(date1) >= 0 && champEtatAtelierse.getDateDebutReelle().compareTo(date2) <= 0) {
champEtatAtelierList2.add(new ChampEtatAteliers(champEtatAtelierse.getNumero(), champEtatAtelierse.getDenominationFr(), "Entree/Mois"));
}
if (champEtatAtelierse.getEtat().equals("OUV")) {
if (champEtatAtelierse.getDateDebutReelle().compareTo(date1) < 0) {
champEtatAtelierse.setEtatEntreeSortie("En instance début du mois");
} else {
if (champEtatAtelierse.getDateDebutReelle().compareTo(date2) <= 0) {
champEtatAtelierse.setEtatEntreeSortie("En instance fin du mois");
}
}
}
}
I think that it's not possible to reference a parameter in the contructor.
in your case it throws a NoSuchMethodexeption : it means that, no method with the current signature in your ChampEtatOT class (5 parameters instead of 8 )
you can refer to this answer => Passing a parameter in a jpql query select
So ,try to retrive all data then make a filter method to set all the etatEntreeSortie values inside the ChampEtatOT class of the ResultList
Clearly the JPQL BNF does permit passing parameters as constructor arguments.
constructor_expression ::= NEW constructor_name ( constructor_item {, constructor_item}* )
constructor_item ::= single_valued_path_expression | scalar_expression | aggregate_expression |
identification_variable
scalar_expression ::= simple_arithmetic_expression | string_primary | enum_primary |
datetime_primary | boolean_primary | case_expression | entity_type_expression
string_primary ::= state_field_path_expression | string_literal |
input_parameter | functions_returning_strings | aggregate_expression | case_expression
i.e a scalar_expression can be a string_primary, which can be an input_parameter. So your JPA provider is not meeting the JPA spec and you should raise a bug on it.