OGNL class keyword handling - ognl

I would like to translate this java code to OGNL code:
SomeClass.class.getDeclaredFields()
I tried in OGNL:
#SomeClass.class#getDeclaredFields()
but I got
java.lang.ClassNotFoundException: Unable to resolve class: SomeClass.class

First getDeclaredFields is not static. So it needs "."(dot).
For class use # as it would be static field.
Use
#SomeClass#class.getDeclaredFields()

Related

Calling a static method from Thymeleaf TEXT template - how to bypass the Restricted mode

Is it possible to call a static method from a Thymeleaf textual template?
Official guide mentions that it should be possible to call a method like this:
<p th:text="${#myapp.translator.Translator#translateToFrench(textVar)}">Some text here...</p>
When I try to use it in my textual template (TemplateResolver's mode is set to TemplateMode.TEXT), I get a this exception:
org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating OGNL expression: "#java.lang.System#currentTimeMillis()" (template: "template.txt" - line 1, col 18)
Here is my sample template:
System millis: [(${#java.lang.System#currentTimeMillis()})]
After googling for a while, I also found this form of calling methods:
System millis: [(${T(java.lang.System).currentTimeMillis()})]
which fails with the same error.
What I need to do is somehow allow usage of a custom number formatter class from a template (functionality of the #numbers utility object is not rich enough for my case).
I can call methods on a non-static class by providing it as a context variable like this:
Some value: [(${formatter.format(someValue)})]
but it would be easier for me to use a static class without a need to explicitly adding it to each template's context.
BTW, I do not use Spring, just pure Thymeleaf.
Update
I should've spend more time to analyze the stack trace of the Thymeleaf exception I got.
It turns out, that the root cause of this behavior was the org.thymeleaf.exceptions.TemplateProcessingException: Instantiation of new objects and access to static classes is forbidden in this context exception, which is results from this change: https://github.com/thymeleaf/thymeleaf/issues/809
Downgrading to Thymeleaf 3.0.11 "fixes" it.
Now I'm looking for a solution to bypass this new Resctricted mode on the latest Thymeleaf (3.0.12 for the moment). I'm sure it's safe in my case, because I'm the only author of both code and templates.
An alternative would be to use the th:with attribute. It's a little more verbose, but still should allow you the same flexibility. (This works for me on 3.0.12.RELEASE.)
[# th:with="time=${#java.lang.System#currentTimeMillis()}"]System millis: [[${time}]][/]
https://github.com/thymeleaf/thymeleaf/issues/816#issuecomment-826401631 has extensive info on why this was done and possible workarounds. In your case, it will be best to add a model attribute in your controller and use that instead of calling the static method in the template.
#Controller
public class MyController {
public String myControllerMethod(Model model) {
model.addAttribute("time", System.currentTimeMillis());
return "name-of-the-thymeleaf-template";
}
}
and update your template to use:
System millis: [(${time})]

grails 2.5+ Duplicate class definition error when implementing serializable on a controller

Upgrading a legacy system of grails. One of the controllers implements Serializable. This is throwing the following error in newer versions of grails:
Invalid duplicate class definition of class com.regional.ScheduleController :
The source contains at least two definitions of the class.
One of the classes is an explicit generated class using the class statement,
the other is a class generated from the script body based on the file name.
Solutions are to change the file name or to change the class name.
The solution mentioned would break (previous) grails convention. Anyone know how to handle this in grails 2.5+?
EDIT
Serializable is not the issue. I tried removing it and got the same error.
I found this explanation from another question:
IN groovy.. class B{} is a class structure and defines a class B.
Scripts are classes too.
Now you may create a B.groovy, with the content "class B{}; def b = new B()".
There would be one class named B, and a script with the very same name.
This is a conflict.
However this does not explain why it runs fine below grails 2.5 and not above it. And I can't find a def conflict like the one mentioned above in that controller.
ANSWER:
One of the imports was what was actually failing- in a way that caused groovy to generate a class definition based on the current file name. When it hit the class definition, there was already an auto generated class name to collide with.

Grails access Config properties in Secured annotation

I am trying to access the Config of the grails application via the #Secured annotation of spring security with the aim to externalize the role name later.
Sadly, I wasn't able to get this working. Neither by trying to use deprecated ConfigurationHolder class nor getting reference to grailsApplication object.
import org.codehaus.groovy.grails.commons.ConfigurationHolder as CH
#Secured([CH.config.grails.app.user])
class MyController { ...}
Config.groovy:
...
grails.app.user = "ROLE_APPNAME_USER"
...
Does anyone have an advice how to solve this?
EDIT
Came across Burt's article which was informational.
You can't - annotation element values must be compile-time constants because they're resolved by the compiler and stored as part of the class bytecode.
You may have more luck using one of the other mechanisms to specify security constraints (static rules or Requestmap instances in the database) instead of annotations.

Custom Routing with symfony 1.4

I want to extend symfony's default router. I have created routing folder in lib/ and created customRouter.class.php saved it under lib/routing. I have changed factories.yml as below:
all:
routing:
class: customRouter
My customRouter.class.php is:
class customRouter extends sfPatternRouting{
}
I only extend sfPatternRouting class. When I run the application it gives me an error as below:
Catchable fatal error: Argument 1 passed to sfRouting::__construct() must be an instance of sfEventDispatcher, string given in /opt/task/lib/vendor/symfony/lib/routing/sfRouting.class.php on line 32
I do not realize the problem. I only extend the class. What is the solution to extend symfony's router?
I believe you are extending the wrong class and as such are not inheriting necessary methods. The symfony 1.4 documentation suggests extending the 'sfDoctrineRoute' class to create custom routing (as linked by #Kenny)

Groovy Mixins?

I'm trying to mix-in a class in my Groovy/Grails app, and I'm using the syntax defined in the docs, but I keep getting an error.
I have a domain class that looks like this:
class Person {
mixin(ImagesMixin)
// ...
}
It compiles fine, but for some reason it won't work. The file containing ImagesMixin is located in my /src/groovy/ directory.
I've tried it using Groovy versions 1.5.7 and 1.6-RC1 without any luck. Does anyone know what I'm doing wrong?
stacktrace:
2008-12-30 17:58:25.258::WARN: Failed startup of context org.mortbay.jetty.webapp.WebAppContext#562791{/FinalTransmission,/home/kuccello/Development/workspaces/lifeforce/FinalTransmission/web-app}
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'pluginManager' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Invocation of init method failed; nested exception is java.lang.ExceptionInInitializerError
at java.security.AccessController.doPrivileged(Native Method)
at RunApp_groovy$_run_closure2_closure7.doCall(RunApp_groovy:67)
at RunApp_groovy$_run_closure2_closure7.doCall(RunApp_groovy)
at Init_groovy$_run_closure6.doCall(Init_groovy:131)
at RunApp_groovy$_run_closure2.doCall(RunApp_groovy:66)
at RunApp_groovy$_run_closure2.doCall(RunApp_groovy)
at RunApp_groovy$_run_closure1.doCall(RunApp_groovy:57)
at RunApp_groovy$_run_closure1.doCall(RunApp_groovy)
at gant.Gant.dispatch(Gant.groovy:271)
at gant.Gant.this$2$dispatch(Gant.groovy)
at gant.Gant.invokeMethod(Gant.groovy)
at gant.Gant.processTargets(Gant.groovy:436)
at gant.Gant.processArgs(Gant.groovy:372)
Caused by: java.lang.ExceptionInInitializerError
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:169)
at Episode.class$(Episode.groovy)
at Episode.<clinit>(Episode.groovy)
... 13 more
Caused by: groovy.lang.MissingMethodException: No signature of method: static Person.mixin() is applicable for argument types: (java.lang.Class) values: {class ImagesMixin}
at Broadcast.<clinit>(MyClass.groovy:17)
... 17 more
2008-12-30 17:58:25.259::WARN: Nested in org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'pluginManager' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Invocation of init method failed; nested exception is java.lang.ExceptionInInitializerError:
groovy.lang.MissingMethodException: No signature of method: Person.mixin() is applicable for argument types: (java.lang.Class) values: {class ImagesMixin}
at Broadcast.<clinit>(Person.groovy:17)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:169)
at Episode.class$(BelongsToMyClass.groovy)
at Episode.<clinit>(BelongsToMyClass.groovy)
at java.security.AccessController.doPrivileged(Native Method)
at RunApp_groovy$_run_closure2_closure7.doCall(RunApp_groovy:67)
at RunApp_groovy$_run_closure2_closure7.doCall(RunApp_groovy)
at Init_groovy$_run_closure6.doCall(Init_groovy:131)
at RunApp_groovy$_run_closure2.doCall(RunApp_groovy:66)
at RunApp_groovy$_run_closure2.doCall(RunApp_groovy)
at RunApp_groovy$_run_closure1.doCall(RunApp_groovy:57)
at RunApp_groovy$_run_closure1.doCall(RunApp_groovy)
at gant.Gant.dispatch(Gant.groovy:271)
at gant.Gant.this$2$dispatch(Gant.groovy)
at gant.Gant.invokeMethod(Gant.groovy)
at gant.Gant.processTargets(Gant.groovy:436)
at gant.Gant.processArgs(Gant.groovy:372)
2008-12-30 17:58:25.271::INFO: Started SelectChannelConnector#0.0.0.0:8080
Since Groovy 1.6 you can either apply a mixin at compile-time to a class using an annotation
#Mixin(ImagesMixin)
class Person {
}
Or you can apply the mixin at runtime like this:
def myMixin = ImagesMixin
Person.mixin myMixin
The latter approach is more dynamic as the class to mixin can be determined at runtime. Further information about Groovy mixins is available here.
In my experience, a lot of meta-programming of domain classes simply doesn't work. I don't exactly know why, but suspect it's due to the fact these classes are already very heavily meta-programmed by the Grails runtime. In general my approach is
Try the meta-programming on a POGO in the Groovy console
If that works, try it on a non-domain class in the Grails console
If that works, try it on a domain class in the Grails console. If it doesn't work, then it must be because it's a domain class (rather than a problem with the syntax). At this point it's advisable to try and find another way of accomplishing your goal. If that's not possible, then use a combination of the Grails mailing list and/or Stackoverflow and/or the Grails source code to try and get the meta-programming working.
I don't think you are using the proper mixin syntax. Try this:
class MyMixin {
static doStuff(Person) {
'stuff was done'
}
}
class Person {}
Person.mixin MyMixin
new Person().doStuff()
I guess what you've seen there is rather a proposal than a feature ;) Groovy does not support mixins out of the box in this way yet (if ever). But there is a 3rd party lib that can be used to emulate such a behavour: Injecto. And mixins can be defined using AST-Macros in the 1.6 version of Groovy (which is not final yet).
You should always check if your're reading the docs from the real groovy project or from the GroovyJSR project (which is rather a place where proposals are collected).
Another way is to use plain-old MOP to inject behaviour into groovy classes by modifying metaClasses.
Cheers
In case this helps anyone, Following on from #virtualeyes comment above, I've found that
Person.doStuff()
fails unless you call the following first:
new Person().doStuff()
Person.doStuff()
after which, the static method on the class does seem to work (for me, using Grails 2.2.4) I guess it's to do with initialising the class, or something, but I tried:
Person.metaClass.initialize()
Person.doStuff()
and that didn't work!
FYI: There is such a thing as "embedded" domains in Grails now, but it has problems. This is where you can logically include one domain as part of another and have its fields all occur physically in the one DB table. For example, if you find that you have the same subset of fields appearing in multiple tables, like street address/city/state/zip, you could define a StreetAddress domain and embed it. One of the current problems is that Grails will still create a street_address table in addition to embedding its fields in the other tables (unless you play tricks). There are submitted patches pending for this, it seems.
Grails domain objects are already heavily meta-programmed.
Instead of the groovy mixin try:
#grails.util.Mixin(ImagesMixin)
class Person {
}
Use Traits!
Traits are the reason they removed support for mixins, because that are just better. They're basically abstract classes that are implemented. Allowing you to use multiple and operate them as partial classes.
trait A {
void printSomething() {
println "foobar"
}
}
class B implements A {
void printAnything() {
printSomething()
}
}
new B().printAnything()
Try it out!

Resources