Grails validation errors disappear from service to controller - grails

When I do custom rejectValue in a service method grails loses that error(s) between service method and return to controller. This seems to happen when updating a row instance, but not when creating one.
In service
def specialValidation(petInstance){
if(petInstance.petType.requiresStateId && !petInstance.StateId){
petInstance.errors.rejectValue('StateId','StateId required');
}
println petInstance.errors //shows 1 error
return petInstance;
}
In controller
...
petInstance.properties=params;
petInstance=petService.specialValidation(petInstance);
println petInstance.errors //shows 0 errors
How is the error being lost when the instance changes hands from service to controller?

It can be because of transactional service. Service opens separate transaction for each method and clears entities after method end. You can find this mentioned in docs(read the last paragraph of part )
I had the same problem. Than I've added NotTransactional annotation to validation method, and it helped. Errors were saved.

Well I did something simular :
orderService.validate(order, params)
if (order.hasErrors()) {
return render(view: 'create', model: [order: order])
}
In the Service I do some validation like this:
if (end.before(start)) {
order.errors.rejectValue("end", '', 'ERROR');
}
The different to yours is that i didn't set the errorCode but the message at itself, have a look at the rejectValue Methods:
void rejectValue(String field, String errorCode);
void rejectValue(String field, String errorCode, String defaultMessage);
You could also try to use the rejectValue method like me, maybe it helps.

I found you can also avoid this by using
MyDomain.read(id)
instead of
MyDomain.get(id)

Related

How to know if data was persisted during database transaction after method returning?

I have a method written in a Grails service, which processes a lot of data.
I noticed that, sometimes, the method returns success but the data is not persisted to the database.
I debugged it, following all the data till the end of the method and everything is fine, however data is not persisted.
The following image demonstrates the what I just explained. You can see the end of the method, in which a Map object is filled with persistent object metadata. Even you can see the console which contains the printend Hibertate SQL
How can I detect whether a rollback mechanism is thrown after successful method returning?
This is my connection properties for Oracle 12c database. Others configurations are Grails defaults
dataSource.pooled=true
hibernate.jdbc.use_get_generated_keys=true
hibernate.cache.use_second_level_cache=true
hibernate.cache.use_query_cache=false
hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory
dataSource.driverClassName=oracle.jdbc.driver.OracleDriver
dataSource.dialect=org.hibernate.dialect.OracleDialect
dataSource.url=jdbc:oracle:thin:#172.16.1.20:1521:db
dataSource.username=<USER>
dataSource.password=<PASS>
hibernate.default_schema=<SCHEMA>
The service is anotated as #Transactional
#Transactional
class SincronizacionService {
}
Any Idea?
When using GORM's save method, also use failOnError:true. By default, save method silently fails. However, if you use failOnError:true, it will throw an exception if the data is not persisted.
If you do not want to stop the program when the data fails to save, you can use the try-catch block to log data that failed to save and let the algorithm continue to do it work.
Hope that helps.
I found the problem. In this method actaDenunciaService.generarActaDenuncia(denuncia), there is a peculiarity. In a part of the method is located the following snippet:
try {
DNomenclador nomenclador = nomencladorService.obtenerNomencladorDNomenclador(meta.valor.toLong())
if (!nomenclador) {
return toReturn(limpiarTexto(meta.valor))
} else {
return toReturn(nomenclador.valor)
}
} catch (Exception e) {
return toReturn(limpiarTexto(meta.valor))
}
A team member changed this line nomencladorService.obtenerNomencladorDNomenclador(meta.valor.toLong()). The change represented a huge improvement of memory saving. However, the team member did not take into account a business process, which does not take into account the method he used.
Yes, a runtime exception is being thrown.
And the treatment, depending on the objective of the method, is correct
For the future, this is how the method will be from now on:
try {
DNomenclador nomenclador = nomencladorService.obtenerNomencladorDNomencladorLibre(meta.valor.toLong())
if (!nomenclador) {
return toReturn(limpiarTexto(meta.valor))
} else {
return toReturn(nomenclador.valor)
}
} catch (Exception e) {
e.printStackTrace()
return toReturn(limpiarTexto(meta.valor))
}
nomencladorService.obtenerNomencladorDNomencladorLibre(meta.valor.toLong()) for the business process
e.printStackTrace() for tracing any other peculiarity
Thanks a lot to everybody who had collaborated on finding this error
I found the error!
An error thrown inside a method for generating a PDF document with data, appearsto be failing. The second line shows this
try {
denuncia.xmlFirmadoServ = dfileManagerService.guardarDFile(signatureResponse.resultado, "xmlfirmadoservidor.xml", usuario)
denuncia = actaDenunciaService.generarActaDenuncia(denuncia).denuncia
} catch (Throwable t) {
denunciaUtilService.incrementarNumeroDenuncia(true)
throw t
}
Now, the new question is: If the method is encapsulated inside a try/catchblock, why the catch block is not excecuting?
When I comment the 2nd line inside try/catch block, data is persisted on database
With no comments, generation PDF method is executed till the end, doing all what it must do

Return response object in event listener not working when triggered in controller plugin

I implemented a shared event listener that manipulates and returns the response object with an error template showing the message of the triggered error code. (I'm not talking about throwing exceptions and catching them in a dispatch.error listener!)
This works fine when I call this event in a controller action. However, when I trigger my error event in a controller plugin that is called in the onDispatch method of the controller, only the status code is set correctly. But the called action is fully executed and no error page is shown.
I have absolutely no idea why this happens and I hope, someone is able to explain me the dispatch/event triggering/short circuiting/returning response issue here.
Following extracts might give you an impression of my code:
Listener:
class SharedErrorListener implements SharedListenerAggregateInterface {
...
public myErrorFunction(EventInterface $e) {
// get error code
// set status code to injected response object
// add error template to injected view model
// return response
}
}
Random controller action (works fine):
return $this->getEventManager()->trigger('error', $this, array(
'errorCode' => my_error_code
));
onDispatch() of controller:
// call plugin, if return value given return it (response must be returned?!).
$r= $this->plugin('myplugin')->doIt();
if (isset($r)) {
return $r;
}
class myplugin doIt() where error is triggered, but error template not showing up:
return $this->getController()->getEventManager()->trigger('error', $this, array(
'errorCode' => my_error_code
));
As the code in the controller and the controller plugin ist pretty much the same, I think it must depend on some application state. I did a lot of research, but couldn't find, what the problem might be. But as the event is triggered correctly and also the right status code is set to the response, I am just very confused. I don't want to implement an ErrorController (which would allow to call a redirect), because I think the solution via EventManager is actually very nice.
I'm too busy to actually read all the above, but from what my impression is, this code-snipped may actually help you out:
$trigger = $this->getEventManager()->trigger(self::EVENT_IDENTITY_GET, $identity);
if ($trigger instanceof ResponseCollection && !is_null($trigger->last())) {
return $trigger->last();
}
I finally found the problem here. By returning the response during the onDispatch process, the onDispatch() of the AbstractActionController wasn't called. In that function the return value of the controller action, e.g. the view model, is set as "result" of the MvcEvent. I just had to set the template that was set in the listener as the result for the event:
$r = $this->plugin('my_plugin')->doIt();
if ($r instanceof ResponseCollection) {
$e->setResult($this->getServiceLocator()->get('view_manager')->getViewModel()->getChildren());
return $r;
}
Hope this helps someone.

Grails datasource becoming null in Service

I am using Grails 2.2.1, and I have a custom dataSource injected into the service so that I can execute some SQL queries.
Upon first execution, there is a dataSource, but on each subsequent call, the reference to the dataSource has become null.
class ReportService {
def dataSource_myds
Object[] reportRecords(int a) {
String query = "SELECT ..."
Object[] resultSet;
Sql sql = new Sql(dataSource_myds)
// ^ Here the NullPointerException is thrown
// But it always works at the first execution
sql.eachRow(query, [a]) {
...
resultSet += result
}
return resultSet
}
}
class ReportController {
ReportService reportService
def report = {
...
Object[] resultSet1 = reportService.reportRecords(1)
...
Object[] resultSet2 = reportService.reportRecords(2)
// ^ java.lang.NullPointerException : Must specify a non-null Connection
...
}
}
Has anyone ever seen this before, and if so, how can I avoid this?
Here is my DataSource.groovy
environments {
development {
dataSource_myds {
url = "jdbc:oracle:thin:#..."
driverClassName = "oracle.jdbc.driver.OracleDriver"
username = "..."
password = "..."
}
}
}
Try, to use resources.groovy way as well. This will also give you option for environment basis datasource.
Explained well on the link given below:
Grails 2 multiple dynamic datasources in services
Thanks
Solved avoiding 2 subsequent calls to the service. It seems the framework nulls the service connection after the first call from the controller.
James Kleeh's comment solved it for me - grails clean and then restart the app.
I had a similar issue and I got it fixed. Firstly, make sure your Service class is in the grails-app/services folder. Secondly, you need to make sure you get the object of the service class using the injection mechanism and not by using the constructor. I had my service class in the right folder but I was trying to create the instance of the service class as MyService.instance in my controller and having the issue of null dataSource/connection. Then I tried def myService in my controller instead of MyService.instance and it worked. Hope this helps. Thanks

Grails service - invoking method from controller?

I'm trying to call a method on a grails service from a controller, but it looks like execution is just skipping the method call.
I've tried debugging the application with a breakpoint inside the method but it is never hit.
My service (generated with grails create-service) is:
class FormatterService {
static transactional = false
def formatList (List<Host>, String fmt) {
OutputObject somePOGO = new OutputObject();
(snip)
return somePOGO
}
}
Then on my controller I have:
class HostController {
def formatterService
def getHostsByLabels = {
(snip)
OutputObject o = formatterService.formatList(someHosts,params.format)
(snip)
}
}
When the formatterService.formatList method should be called in the controller, execution simply skips to the next line, no output is printed to the console and breakpoints within the method are not hit. The OutputObject o reference is null afterward.
What is wrong here? It could be a really basic mistake from my part, but I just can't put my finger on it...
To Me it seems a MetaProgramming Disaster..
Well there are 3 Tests to Debug:
_1) first try to do
println formatterService
println formatterService.getClass()
just to check if its injected bean is the desired one, some plugins sometimes inject beans which overrides the default.
_2) Make sure that the method with a name "formatList" is not injected in your services through metaprogramming by any plugin or core code.
How to test this is simple: Just change the name of the method to some Unrealistic One, ex: "formatListabcdewdw" and then call that one. If it works then its method overriden issue.
and if you are more enthusiastic you can see the metaMethods by
println formatterService.metaClass.methods
_3) just try to do "params.format as String" as the last argument in the method call.\
.
Hope any of these helps, please Do let me know of the findings, i am curious to know.. :)
I found the issue. It has to do with the method signature.
Printing out the thrown exception's message, it says:
No signature of method: hms.FormatterService.formatList() is applicable for argument types: (java.util.TreeSet, java.lang.String) values: (...)
Possible solutions: formatList(java.util.List, java.lang.String)
So, a rookie mistake (wanting to pass a TreeSet for a List) aided by weak typing in Groovy... :P
I've changed the method signature to
def formatList ( items, String fmt) {
and call it as
def activeHosts = ...
OutputObject o = formatterService.formatList(activeHosts, params.format as String)
and now it works.

Groovy give NPE on list.find call but only after a period of time

We have a chunk of code something like this
// semi-pseudo code
def result = someList.find { condition == true }
(someList may be null, but that is ok in groovy as null.find{…} works fine.)
This line of code is running in an action of a grails controller and deployed in production to a server. After a period of time (sometimes hours, sometimes longer) the above line of code will start throwing a NullPointerException — and once it starts throwing the NPE it always throws the NPE.
Through debugging we've proven that it works fine even when someList is null (up until we get the seemingly random first NPE)… also through debugging we were able to get a more detail stacktrace that indicated there error was in Groovy's MetaClassRegistryImpl.java line 214.
I've googled every combination I can think of to see if there are any known Groovy bugs but found nothing of value.
(It is using Grails 1.3.7, thus Groovy 1.7.8)
A JMeter script was setup to run through a series of site interactions that makes this problem semi-repeatable. The script will iterate through 50-100 series and then the error starts appearing - once the error appears it is always in error until the application is redeployed to the server (Glassfish).
Tracing through the groovy code it looks something like this:
//AbstractCallSite.java
public Object call(Object receiver, Object arg1) throws Throwable {
return call(receiver, ArrayUtil.createArray(arg1));
}
//PerInstancePojoMetaClassSite.java
public Object call(Object receiver, Object[] args) throws Throwable {
if (info.hasPerInstanceMetaClasses()) {
try {
return InvokerHelper.getMetaClass(receiver).invokeMethod(receiver, name, args);
} catch (GroovyRuntimeException gre) {
throw ScriptBytecodeAdapter.unwrap(gre);
}
} else {
return CallSiteArray.defaultCall(this, receiver, args);
}
}
//InvokerHelper.java
public static MetaClass getMetaClass(Object object) {
if (object instanceof GroovyObject)
return ((GroovyObject) object).getMetaClass();
else
return ((MetaClassRegistryImpl) GroovySystem.getMetaClassRegistry()).getMetaClass(object);
}
//MetaClassRegistryImpl.java
public MetaClass getMetaClass(Object obj) {
return ClassInfo.getClassInfo(obj.getClass()).getMetaClass(obj);
}
So it appears the NPE is on the obj.getClass() — if that's the case I'm a little baffled how it ever works when someList is null (but that is a separate topic).
FWIW, we are not doing any class or instance level meta-class coding of our own on someList.
Is there a bug in Groovy or what could we possibly be doing wrong to cause a (random) NPE deep in Groovy code?
UPDATE—
The observation is that someList is being set to a 'java null' instead of a 'groovy null' (NullObject). The object is coming from a map (flow context) via a flow in a controller action...
class SomeController {
def someActionFlow = {
action {
def someList = flow.someList
}
}
}
The case in question is when flow.someList has never been set it should always be null (groovy null). flow is just a map so it is the same as doing flow.get('someList')
The above code works fine for an unknown number of iterations and then starts returning 'java nulls' instead of 'groovy nulls'.
I'm going to hazard a guess that it's dependent on how someList is created. That is, if it's created in Groovy as
def someList = null
Then Groovy assigns the NullObject to the variable. However, if the value is returned from some other Java component as a real Java null, then it will throw the NPE. Going further, there might be some optimization in Groovy/Java/JVM where callsite caching is causing it to always return NPE.
Then again, this is just a wild guess.
Fixed: Similarly to GROOVY-5248 (call site caching missing null check), add a receiver null check to avoid NPEs under certain circumstances
commit 641c6a8d4b6b3046f4d8a1a2ac5f08f1f2769f0f

Resources