Grails bean config in resources.groovy fails in Eclipse STS - eclipse

We're using Eclipse STS for a simple Grails project. We started with something simple to understand the basics, and this is about as basic as it gets. The project has a simple controller and a java bean wired through resources.groovy. No matter what we do, we can't seem to get the bean wired properly, Grails complains that the bean property is not writable or may not have a getter/setter....
/* TestBean.groovy */
class TestBean {
def message
String getMessage(){
return message
}
}
.
/* resources.groovy */
import com.ofi.test.TestBean;
beans = {
helloWorldBean( TestBean){
message = "HelloWorld"
}
}
.
/* TestController */
class TestController {
def index = { }
def helloWorldBean
def show = {
def message = helloWorldBean.message
render message
}
}
.
/* UrlMappings.groovy */
class UrlMappings {
static mappings = {
"/test/$var"(controller:"Test"){
action = [GET: "get"]
}
}
.
The project compiles, but we get the following error message when the app loads up in Eclipse (we can't even get to the controller, the TestBean config is failing)
2011-08-10 11:18:55,252 [main] ERROR context.GrailsContextLoader - Error executing bootstraps: Error creating bean with name 'helloWorldBean': Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'message' of bean class [com.ofi.test.TestBean]: Bean property 'message' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'helloWorldBean': Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'message' of bean class [com.ofi.test.TestBean]: Bean property 'message' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
at org.grails.tomcat.TomcatServer.start(TomcatServer.groovy:212)
at grails.web.container.EmbeddableServer$start.call(Unknown Source)
at _GrailsRun_groovy$_run_closure5_closure12.doCall(_GrailsRun_groovy:158)
at _GrailsRun_groovy$_run_closure5_closure12.doCall(_GrailsRun_groovy)
at _GrailsSettings_groovy$_run_closure10.doCall(_GrailsSettings_groovy:280)
at _GrailsSettings_groovy$_run_closure10.call(_GrailsSettings_groovy)
at _GrailsRun_groovy$_run_closure5.doCall(_GrailsRun_groovy:149)

Since your bean is a groovy bean, you don't even need the accessors. The following should be fine:
class TestBean {
def message
}
In your case, the error's probably occurring because the message field is typed as a def, but your accessor is typed as a String. If you must have the accessor there, try typing them the same.

You can add more fields in Bean class and use them into Controller like-
class TestBean {
static constraints = {
}
String message
String name
def demo
}

Related

grails 3.3.9 - extending from restfulController fails with "No default constructor found"

using grails v3.3.9.
got an error when accessing a restful controller. grails web shows this
URI
/api/device
Class
java.lang.NoSuchMethodException
Message
Error creating bean with name 'com.softwood.controller.DeviceController': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.softwood.controller.DeviceController]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.softwood.controller.DeviceController.<init>()
Caused by
com.softwood.controller.DeviceController.<init>()
I have setup UrlMapping like this
get "/api/device"(controller:"device", action:"index")
my controller extends RestfulController like this, which wont permit a default constructor to be added to the class
class DeviceController extends RestfulController<Device> {
static responseFormats = ['json', 'xml']
//static scaffold = Device
DeviceController(Class<Device> device) {
this(device, false)
}
DeviceController(Class<Device> device, boolean readOnly) {
super(device, readOnly)
}
def index (Integer max) {
params.max = Math.min(max ?: 10, 100)
Collection<Device> results = Device.list(sort:"name")
respond results, deviceCount: Device.count()
}
def show (Device device) {
if(device == null) {
render status:404
} else {respond device}
}
}
Theres a link here thats related Extending RestfulController for a base SubClassRestfulController is not working on grails 3.0.4
however i have cleaned the build, re run etc nothing works. I get the same failure to instantiate
What is the fix for this to permit extending from RestfulController ?
my controller extends RestfulController like this, which wont permit a
default constructor to be added to the class
That is not true. Your constructor should not accept a Class as an argument. You want the no argument constructor.
class DeviceController extends RestfulController<Device> {
static responseFormats = ['json', 'xml']
DeviceController() {
super(Device)
/* If you want it to be read only, use super(Device, true)
instead of super(Device)
*/
}
// ...
}
When Spring creates the controller instance, it is not going to pass anything to the constructor so you need the no-arg constructor.

Spring Data and stored procedures

I have a stored procedure with the following declaration:
CREATE PROCEDURE GetAttributesForCategory(IN catId BIGINT(20))
In my Spring Boot-backed app there is an entity:
#Entity
#NamedStoredProcedureQueries({
#NamedStoredProcedureQuery(
name = "ProductAttribute.getAttributesForCategory",
procedureName = "GetAttributesForCategory",
parameters = {
#StoredProcedureParameter(name = "catId",
type = Long.class,
mode = ParameterMode.IN)
}
)
})
public class ProductAttribute {
...
}
And the correspondent repository looks like:
public interface ProductAttributeReposirory extends JpaRepository<ProductAttribute, Long> {
#Procedure(name = "getAttributesForCategory")
List<ProductAttribute> getAttributesForCategory(#Param("catId") Long catId);
}
All is made according to this example, but an exception is occurred during Spring context loading:
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'productAttributeRepository': Invocation of init method failed;
nested exception is org.springframework.data.mapping.PropertyReferenceException:
No property getAttributesForCategory found for type ProductAttribute!
I can't imagine what goes wrong. Anybody can?
I was having the same issue with this, and resolved it by adding an OUT #StoredProcedureParameter:
#StoredProcedureParameter(mode = ParameterMode.IN, name = "inVar", type = String.class),
#StoredProcedureParameter(mode = ParameterMode.OUT, name = "outVar", type = ArrayList.class)
though at this point I'm getting a different error "Parameter index of 2 is out of range"

Why is Guava issuing the error "missing event handler for an > annotated method"?

I'm getting the following error in one of my classes on the when attempting to unregister it.
java.lang.IllegalArgumentException: missing event handler for an
annotated method. Is
[DerivedClass] registered?"
at com.google.common.eventbus.EventBus.unregister(EventBus.java:227)
The class calling unregister(this) has the public #Subscribe annotated method.
The problem was that the error message misled me to think there was something wrong with the annotations. It was in fact that the class was unregistering itself twice due to some unexpected flow of control.
A source code explanation:
/**
* Unregisters all handler methods on a registered {#code object}.
*
* #param object object whose handler methods should be unregistered.
* #throws IllegalArgumentException if the object was not previously registered.
*/
public void unregister(Object object) {
Multimap<Class<?>, EventHandler> methodsInListener = finder.findAllHandlers(object);
for (Entry<Class<?>, Collection<EventHandler>> entry : methodsInListener.asMap().entrySet()) {
Class<?> eventType = entry.getKey();
Collection<EventHandler> eventMethodsInListener = entry.getValue();
handlersByTypeLock.writeLock().lock();
try {
Set<EventHandler> currentHandlers = handlersByType.get(eventType);
if (!currentHandlers.containsAll(eventMethodsInListener)) {
throw new IllegalArgumentException(
"missing event handler for an annotated method. Is " + object + " registered?");
}
currentHandlers.removeAll(eventMethodsInListener);
} finally {
handlersByTypeLock.writeLock().unlock();
}
}
}

Spring List of interface type data binding - how?

Tried to find the answer on the Web but failed. Should be simple for pro Spring Devs... so here it comes:
In few words I want to bind the List of interface type: List to the form and get the data back (possibly modified by user via form. The problem is that it doesn't work :(
my code (short version) - command/model class which is passed to the form:
public class RoomsFormSearchResultCommand extends RoomsFormSearchCommand {
#SuppressWarnings("unchecked")
private List<IRoom> roomsList = LazyList.decorate(new ArrayList<Room>(),
FactoryUtils.instantiateFactory(Room.class));
public List<IRoom> getRoomsList() {
return roomsList;
}
public void setRoomsList(final List<IRoom> roomsList) {
this.roomsList = roomsList;
}
(...)
then in the form I use it like that (short version):
<form:form method="post" action="reserve" commandName="roomsResultsCmd">
(...)
<c:forEach var="room" items="${roomsResultsCmd.roomsList}"
varStatus="status">
<tr>
<td><form:input path="roomsList[${status.index}].roomNumber" readonly="true"/>
(...)
The form is displayed fine but after submitting it I get:
2012-01-22 21:31:55 org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [wyspa] in context with path [/wyspa] threw exception [Request processing failed; nested exception is org.springframework.beans.InvalidPropertyException: Invalid property 'roomsList[0]' of bean class [com.wyspa.controller.command.RoomsFormSearchResultCommand]: Illegal attempt to get property 'roomsList' threw exception; nested exception is org.springframework.beans.NullValueInNestedPathException: Invalid property 'roomsList' of bean class [com.wyspa.controller.command.RoomsFormSearchResultCommand]: Could not instantiate property type [com.wyspa.entity.IRoom] to auto-grow nested property path: java.lang.InstantiationException: com.wyspa.entity.IRoom] with root cause
org.springframework.beans.NullValueInNestedPathException: Invalid property 'roomsList' of bean class [com.wyspa.controller.command.RoomsFormSearchResultCommand]: Could not instantiate property type [com.wyspa.entity.IRoom] to auto-grow nested property path: java.lang.InstantiationException: com.wyspa.entity.IRoom
at org.springframework.beans.BeanWrapperImpl.newValue(BeanWrapperImpl.java:633)
at org.springframework.beans.BeanWrapperImpl.growCollectionIfNecessary(BeanWrapperImpl.java:863)
at org.springframework.beans.BeanWrapperImpl.getPropertyValue(BeanWrapperImpl.java:770)
at org.springframework.beans.BeanWrapperImpl.getNestedBeanWrapper(BeanWrapperImpl.java:555)
(...)
The deal is then when I change the List to "instances" list everything works fine!
public class RoomsFormSearchResultCommand extends RoomsFormSearchCommand {
#SuppressWarnings("unchecked")
//notice that the List is now List<Room>
private List<Room> roomsList = LazyList.decorate(new ArrayList<Room>(),
FactoryUtils.instantiateFactory(Room.class));
In this case data is passed to the controller in proper way.
Since I am used to devlop on interfaces and I am pretty crazy about it I would REALLY prefer not to translate the List<IRoom> (which comes back from services) to List<Room> which seems to suit Spring. Is it possible to work with List<IRoom> in this case or Spring just doesn't support it?
//Of course Room implements IRoom - but I guess you already got that...
I would be VERY happy for any help/suggestions!
Best Regards,
Nirwan
I have exact the same problem. Changing to following won't fix the problem. It looks spring binding ignores the factory utils and tries to instantiate the null object itself:
#SuppressWarnings("unchecked")
private List<IRoom> roomsList = LazyList.decorate(new ArrayList<IRoom>(),
FactoryUtils.instantiateFactory(Room.class));
The workaround is to set auto grow nested path off in your controller:
#InitBinder protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) {
binder.setAutoGrowNestedPaths(false);
super.initBinder(request, binder);
}
The problem is you'll lose the handy nested path like user.account.address.street. You have to make sure none of user, account, addresss is null. It does cause a lot of problems. That's why I came here, see if I can find better solution.
If you don't actually need the list to auto-grow, you can store the form object in the session to avoid the nasty side effects of disabling auto-growing nested paths.
#Controller
#SessionAttributes(types = RoomsFormSearchResultCommand.class)
public final class SearchController {
#InitBinder
protected void initBinder(final WebDataBinder binder) {
binder.setAutoGrowNestedPaths(false);
}
#RequestMapping(method = RequestMethod.GET)
public String showForm(final Model model) {
RoomsFormSearchResultCommand form = ... // create or load form
model.addAttribute(form);
}
#RequestMapping(method = RequestMethod.POST)
public String onSubmitUpdateCart(
#ModelAttribute final RoomsFormSearchResultCommand form,
final BindingResult result,
final SessionStatus status) {
// if result has no errors, just set status to complete
status.setComplete();
}
}
Try the following lines
#SuppressWarnings("unchecked")
private List<IRoom> roomsList = LazyList.decorate(new ArrayList<IRoom>(),
FactoryUtils.instantiateFactory(Room.class));
don't have time to try that myself, but it would make sense.

Bean Validation constraint(s) violated while executing Automatic Bean Validation on callback event: 'prePersist'

I created an EJB Session facade in my Netbeans 7 for saving my entity.
I have a manytoone mapping between my Insurance and RatePlan Class.
public class Insurance{
#ManyToOne(optional=false)
#JoinColumn(name="PLAN_ID")
private RatePlan plan;
}
public class RatePlan{
#OneToMany(mappedBy="plan")
private Set<Insurance> insuranceItems;
}
When I tried saving in my database using my EJB Session Bean, I am encountering below error.
Caused by: javax.validation.ConstraintViolationException: Bean Validation constraint(s) violated while executing Automatic Bean Validation on callback event:'prePersist'. Please refer to embedded ConstraintViolations for details.
What I did was to turn off my Bean validation in my Persistence.xml file.
I would like to know what Bean validation error has occurred but I dont know how or where to find it or how to configure and catch it.
My EJB facade is a simple class like tis.
public class InsuranceFacade{
public void saveInsurance(Insurance insurance){
em.persist(insurance);
}
}
Any hints?
I would like to know what Bean validation error has occurred but I dont know how or where to find it or how to configure and catch it.
To know what specific constraint violations have occurred, you could just inspect the exception caught. ConstraintViolationException.getConstraintViolations() returns a Set of ConstraintViolations which you can iterate and inspect.
I got the same problem, but after hours looking for the answer, Finally I Found it.... You should edit your AbstractFacade.java class and add this code
public void create(T entity) {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<T>> constraintViolations = validator.validate(entity);
if(constraintViolations.size() > 0){
Iterator<ConstraintViolation<T>> iterator = constraintViolations.iterator();
while(iterator.hasNext()){
ConstraintViolation<T> cv = iterator.next();
System.err.println(cv.getRootBeanClass().getName()+"."+cv.getPropertyPath() + " " +cv.getMessage());
JsfUtil.addErrorMessage(cv.getRootBeanClass().getSimpleName()+"."+cv.getPropertyPath() + " " +cv.getMessage());
}
}else{
getEntityManager().persist(entity);
}
}
Now this method will alert you which property and why it fails the validation.
I hope this works for you, as it does for me.
catch (EJBException e) {
#SuppressWarnings("ThrowableResultIgnored")
Exception cause = e.getCausedByException();
if (cause instanceof ConstraintViolationException) {
#SuppressWarnings("ThrowableResultIgnored")
ConstraintViolationException cve = (ConstraintViolationException) e.getCausedByException();
for (Iterator<ConstraintViolation<?>> it = cve.getConstraintViolations().iterator(); it.hasNext();) {
ConstraintViolation<? extends Object> v = it.next();
System.err.println(v);
System.err.println("==>>"+v.getMessage());
}
}
Assert.fail("ejb exception");
}
Catch the following exception where you persisting the entity. In my case its in the EJB add method. where I am doing em.persist(). Then check the server log, you will see which attribute having constrain violation.
catch (ConstraintViolationException e) {
log.log(Level.SEVERE,"Exception: ");
e.getConstraintViolations().forEach(err->log.log(Level.SEVERE,err.toString()));
}