How to create an Enum to use with Grails - grails

Grails 2.2
So this should be pretty easy, however I am constantly getting the same error message:
Class java.lang.IllegalArgumentException
Message No enum constant myPackageName.RequestType.Banner
Here is my class:
public enum RequestType {
BANNER("Banner"), OTHER("Other")
final String value
RequestType(String value) { this.value = value }
String toString() { value }
}
This is driving me up the wall!!
Edit: Stacktrace
No enum constant myPackageName.RequestType.Banner. Stacktrace follows:
java.lang.IllegalArgumentException: No enum constant myPackageName.RequestType.Banner
at java.lang.Enum.valueOf(Enum.java:236)
at org.grails.datastore.gorm.GormStaticApi.methodMissing(GormStaticApi.groovy:108)
at ysuprojects.ProjectService.viewableProjects(ProjectService.groovy:115)
at ysuprojects.ProjectService.getIndexModel(ProjectService.groovy:422)
at ysuprojects.ProjectController.index(ProjectController.groovy:25)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
Here is how it is used in the class
class Project {
...
RequestType requestType
...
}

Ok - so here is what happened.
I switched from using a String to using an Enum. The existing database had "Banner" in the field, which was causing this error. I changed the field to "BANNER" and I no longer receive this error.
Grails was attempting to do Enum.valueOf(RequestType, "Banner")

Related

grails4 migration Traits lazy load issue - HHH000142: Bytecode enhancement failed

I have migrated my application from Grails-3.x to Grails-4.1.1
Most of my Domain classes implemented the following Traits class (DynamicProperties), which has an implementation of GormEntity for some reason - to override the propertyMissing method.
trait DynamicProperties<D> implements GormEntity<D> {
def dynamic = [:]
def propertyMissing(String name, value) {
if (!propertyIsDatasource(name)) {
dynamic[name] = value
}
}
def propertyMissing(String name) {
if (propertyIsDatasource(name)) {
super.propertyMissing(name)
} else {
dynamic[name]
}
}
boolean propertyIsDatasource(String name) {
false
}
}
The above trait has been implemented by many domain classes like this
class Customer implements DynamicProperties<Customer> {
String customerCode
String customerName
Address address
....
}
Now, when I run my application, It is throwing the following exception
HHH000142: Bytecode enhancement failed: com.apps.billing.Customer.
Caused by: java.lang.NullPointerException
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:37)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.call(PogoMetaMethodSite.java:75)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:127)
at **com.apps.billing.common.DynamicProperties$Trait$Helper.$init$**(DynamicProperties.groovy:7)
It used to work fine with Grails3.x
I had a similar problem when migrating a project to Grails 4.0.13.
I tracked the trigger of this problem down to having default values for member variables in a trait class. I see you have the same with the property dynamic being initialized with the empty map.
I recommend lazy initializing it in one of your propertyMissing methods.

Grails 3 Interceptor and render custom JSON view

I am trying to write a Grails 3 interceptor that should check if certain variables are present in the HTTP Headers. If they are not present i would like to render a specific json view but it seems that the render method is not availble in the before() method.
boolean before() {
String header = request.getHeader("Authorization")
if(!header) {
BaseException exception = new BadRequestException("test")
render view: "/genericErrorReponse", model: [e: exception]
return false
}
Is there a better way to achieve the desired result?
I am getting the following error when trying to render the JSON view.
No qualifying bean of type [org.springframework.web.servlet.ViewResolver] is defined.
No qualifying bean of type [org.springframework.web.servlet.ViewResolver] is defined: expected single matching bean but found 4: groovyMarkupViewResolver,jsonViewResolver,beanNameViewResolver,mvcViewResolver. Stacktrace follows:
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.springframework.web.servlet.ViewResolver] is defined: expected single matching bean but found 4: groovyMarkupViewResolver,jsonViewResolver,beanNameViewResolver,mvcViewResolver
at grails.artefact.Interceptor$Trait$Helper.render(Interceptor.groovy:254) ~[grails-plugin-interceptors-3.1.1.jar:3.1.1]
at device.registration.RegistrationInterceptor.before(RegistrationInterceptor.groovy:13) ~[main/:na]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) ~[na:1.8.0_66]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) ~[na:1.8.0_66]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_66]
Interceptor Code
class RegistrationInterceptor {
boolean before() {
String header = request.getHeader("Authorization")
if(!header) {
render view: "/genericErrorResponse", model: [e: new BadRequestException()]
}
false
}
boolean after() { true }
void afterView() {
// no-op
}
}
JSON View [/genericErrorResponse]
model {
BaseException e
}
response.status e.status
json {
message e.message
error e.error
status e.status
timestamp e.timestamp
}
Stacktrace shows that you are trying to get a bean of type org.springframework.web.servlet.ViewResolver at RegistrationInterceptor.groovy:13. Grails has by default 4 different implementations for ViewResolver and you have to be specific which one do you want to use.
It seemed that it actually was a bug inside Grails 3. Please see https://github.com/grails/grails-core/issues/9688

Grails plugin filterPane associatedProperties doesn't work for java.net.URL

I want to have a filter on the class below ("Debate"). By default I get a filter containing title, published and url. That is fine but when I try filter on the URL I get the following exception. "java.lang.String cannot be cast to java.net.URL", see bottom for a full stack trace.
To get around this I added an associatedProperties of url.authority, see below. I figure, since filterpane is comparing to a string I'll give it a string (url.authority).
The problem is the associatedProperties of url.authority never appears on the filter.
I looked through the filterpane code and I can see the following code
// Extract out the associations. These are handled separately from simple properties.
List associatedProps = persistentProps.findAll {
it.association == true && !it.type.isEnum()
}
This is excluding url.authority because url.authority is not a separate domain. I could put url into a domain and I'm guessing it would work but I'd rather not do that as it is altering my underlying code to cater for a plugin and this is very bad practice.
class Debate
{
String title;
Date published;
URL url;
static constraints =
{
url nullable : false, unique : true
}
}
By the way, I tried without the excludeProperties and it makes no difference.
<filterpane:filterPane dialog="true" domain="com.content.OpenDebate"
associatedProperties="url.port" excludeProperties="url"/>
Stack Trace
java.lang.String cannot be cast to java.net.URL. Stacktrace follows:
java.lang.ClassCastException: java.lang.String cannot be cast to java.net.URL
at grails.orm.HibernateCriteriaBuilder.invokeMethod(HibernateCriteriaBuilder.java:1587)
at org.grails.plugin.filterpane.FilterPaneService$_doFilter_closure4.doCall(FilterPaneService.groovy:153)
at org.grails.plugin.filterpane.FilterPaneService.doFilter(FilterPaneService.groovy:156)
at org.grails.plugin.filterpane.FilterPaneService.filter(FilterPaneService.groovy:12)
at com.keane.reg.opendebate.OpenDebateController$_closure1.doCall(OpenDebateController.groovy:29)
at grails.plugin.cache.web.filter.PageFragmentCachingFilter.doFilter(PageFragmentCachingFilter.java:200)
at grails.plugin.cache.web.filter.AbstractFilter.doFilter(AbstractFilter.java:63)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
BTW: Why in the world am I restriced in the tags I can use to describe this post. I have to have a reputation of 1500 or higher to include the words filterpane and associatedproperties. This makes my post less likely to be answered.
So I've spent enough time on this. I have a workaround.
I added an extra field to my domain class. This provides the url.authority I wanted to filter on.
I have excluded the url from the filter and added author.
see the code below.
class Debate
{
String title;
Date published;
URL url;
// author derived from url
String getAuthor()
{
return(url.authority)
}
void setAuthor(String s)
{
// do nothing, just a dummy.
}
static constraints =
{
url nullable : false, unique : true
}
#Override
String toString()
{
return "${url} : ${title} : ${author} : ${published}";
}
<filterpane:filterPane dialog="true" domain="com.content.OpenDebate"
filterProperties="${['author', 'title', 'published']}"
filterPropertyValues="${[published:[precision:'day']]}"/>

Set in domain not working after upgrading grails

Recently I upgraded grails from 1.3.4 to 2.2.2 and I'm getting following error while trying to iterate over a Set defined as hasMany in a domain.
class A {
String name
static hasMany = [bList: B]
}
class B {
static belongsTo = [a:A]
}
class TestController {
def test = {
A a = A.get(1L)
def bList = a.bList
bList.each{}
}
}
Above line bList.each {} is throwing following exception
java.lang.IllegalArgumentException: wrong number of arguments
at
org.grails.datastore.mapping.engine.event.AbstractPersistenceEventListener.onApplicationEvent(AbstractPersistenceEventListener.java:46)
at
com.test.TestController$_closure2.doCall(TestController.groovy:5)
at
java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
at java.lang.Thread.run(Thread.java:680)
So I found the issue
Class B had a afterLoad() event hook attached to it which for some weird reason was throwing java.lang.IllegalArgumentException: wrong number of arguments exception I have now changed it to onLoad() Happy Days Now.
Thanks
Hussain

NoSuchMethodException in Struts2

I have textfield for birthDate. When a user enter invalid date, let say for example a String, error message successfully displayed as fielderror. But in my console, I got this error:
java.lang.NoSuchMethodException: Profile.setBirthDate([Ljava.lang.String;)
Have I missed something that's why I encountered the error?
In your Action class you dont have a method called setBirthDate(String birthDate), add it your issue should be resolved.
Note check to see that you have placed all getter and setter in your action class for all properties.
I think in your JSP you have :
<s:textfield name="birthDate" />
Struts will try to map this to setBirthDate(String string), since this method is missing in your action hence the NoSuchMethodException
Update:
To convert String to Date:
public class MyStringToDateConverter extends StrutsTypeConverter {
public Object convertFromString(Map context, String[] values, Class toClass) {
//Parse String to get a date object
}
public String convertToString(Map context, Object o) {
// Get the string from object o
}
}
If you are using Annotation in your action class then add #Conversion() to your action
#Conversion()
public class MyAction extends ActionSupport{
public Date myDate = null;
#TypeConversion(converter="MyStringToDateConverter") //Fully qualified name so if this class is in mypackage then converter will be "myPackage.MyStringToDateConverter"
public void setMyDate(Date date) {
this.myDate = date;
}
}
If you dont want to use Annotation then you can look at the official documentation for example.

Resources