BeanItemContainer usind a POJO with Inheritance

Hello Everyone,

I am using a BeanItemContainer with two concrete Classes:

Mountainbike and RaceBike

These Classes inherit from Bike which implements myInterface.
Bike has several Attributes ( protected ) with getter and setter (public).

Using these concrete classes (Mountain- RaceBike) with the Bean Item Container does not work as needed.
The attributes inherited from Bike are not visible / used.
If I create an Instance of Bike and use it with the Container, all is fine.

Why are attributes of a SuperClass not used in Child Class Beans?
What is the most elegant way to overcome that issue?

Thanks for your Help in advance!

I believe I have the opposite problem…

I have an abstract base class, let’s call it “BaseBean”. There are some concrete subclasses, say “BeanA” and “BeanB”.
When working with a BeanItemContainer I can only access properties of BaseEntity, but not the ones of of the subclasses.
This is understandable because the bean’s property descriptors are detected during construction of the BeanItem - BUT: what shall I do?
Is there a best practice for this? (And please don’t let it be “do not use inheritance”…)

Thanks!

The attributes of the superinterface of myInterface should be visible.

If you are using an old 6.x version of Vaadin, it might be that you are running into a peculiarity of Java Introspector concerning superinterfaces. Current Vaadin 6.x and 7 versions contain a workaround for this so it should work.

Note, though, that if you give an interface as the type parameter for BeanItemContainer, the container cannot know what will be the concrete classes used and their superclasses. Thus, no properties from them will be shown - all properties are scanned early during container creation based on the given Class object that matches the generic type, and all items of the container must have the same properties.

The container would need to have property instances for the extra items that return an empty value (e.g. null) when the property is not supported by the actual bean.

How I would do it would be to extend the container class you are using so that the constructor can take e.g. the base interface/class and a list of concrete classes. It could then scan the concrete classes for additional properties not in the base class and then loop over the set of all of them, calling the protected addContainerProperty(propertyId, propertyDescriptor) with a custom VaadinPropertyDescriptor implementation that creates custom Property instances that return null (or some other suitable empty value) for properties that are not in the bean instance, otherwise using MethodProperty.

This might sound a bit complicated, but the needed subclasses of e.g. MethodPropertyDescriptor and Bean(Item)Container should be fairly straight-forward to implement based on the superclasses and can easily be reused elsewhere, and most of them would only need to override a few methods.

If there can be similarly named properties in subclasses that are declared in different classes, this gets slightly more complicated. As long as their return types are the same, the easiest solution for that would probably be the CustomPropertyDescriptor having a map from the actual bean class to the property type instead of a single type, and creating some kind of a NullProperty (trivial implementation of a read-only property always returning null, no real listeners etc. needed as value cannot change) when there is no mapping. If the return types can differ, the property type returned by CustomPropertyDescriptor would need to represent a common supertype of the possible values, possibly Object.

It would have almost been quicker to write an implementation than this reply, but testing it properly would take considerably more time…

This could be published as an add-on for the benefit of other users. You could also
create an enhancement request
to include some such functionality in the framework, though the actual API and implementation would need much more thought in that case.

Hello Henri,

thanks a lot for your reply. As you suggested, I created an enhancement request: http://dev.vaadin.com/ticket/11618

Meanwhile I will try my luck subclassing the BeanItemContainer and maybe publish it if it seems good enough.

Thanks again,
Gunnar

I spent some time extending the BeanItemContainer etc., but as it seems I have the most complicated case (e. g. the subclasses all have a member “defaultValue” which has a different type per class). So I stopped working on that and instead implemented a workaround for my specific situation.
However, I’d be glad if the enhancement will find its way into a future Vaadin version.

I have been trying out Vaadin 7. Firstly, I must admin that I am quiet a noob at Vaadin and not much familiar with JAVA persistance. I am thus trying to learn bean validation and how to use it. I have followed couple of tutorials, but its really hard to decide which is the latest and correct one for Vaadin 7. Nonetheless, I tried downloading and using the JPA container and the BeanValidator and I can’t get it working. Here is the code I am using:

package com.example.firstvaadin;
import java.io.Serializable;

import org.hibernate.validator.constraints.Email; import javax.validation.constraints.*;

public class RegisterBean implements Serializable{

public RegisterBean(String email){
this.email = email;
}

@Size(min = 5, max = 50)
private String email;

public void setEmail(String email) {
this.email = email;
}

public String getEmail() {
return email;
}
}

and

RegisterBean rbean = new RegisterBean(“”);
BeanItem item = new BeanItem(rbean);
TextField email = new TextField(“email”,item.getItemProperty(“email”));
email.setImmediate(true);
layout.addComponent(email);
email.setNullRepresentation(“”);
but I hit run-time exceptions on the following Code: email.addValidator(new BeanValidator(RegisterBean.class, “email”));

The exception is:
aused by: com.vaadin.event.ListenerMethod$MethodException: Invocation of method buttonClick in com.example.firstvaadin.LoginView$1 failed.
at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:528)
at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:167)
at com.vaadin.server.AbstractClientConnector.fireEvent(AbstractClientConnector.java:984)
at com.vaadin.ui.Button.fireClick(Button.java:367)
at com.vaadin.ui.Button$1.click(Button.java:56)
… 28 more
Caused by: java.lang.NoClassDefFoundError: javax/validation/MessageInterpolator$Context
at com.example.firstvaadin.RegisterView.(RegisterView.java:55)
at com.example.firstvaadin.LoginView$1.buttonClick(LoginView.java:63)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:508)
… 32 more
Caused by: java.lang.ClassNotFoundException: javax.validation.MessageInterpolator$Context
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1713)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1558)
… 39 more
I have no idea which classes are missing and I have added hibernate jars and validation-api.jar

Can someone please give me a hand?

Last weekend, I put together a first draft of such an implementation.

I haven’t published it in the Directory yet because of a few limitations (requires explicit bean IDs, returns Object as property type if conflicting types in subclasses, only tested in read-only mode), but you can
get it from GitHub
if you want to give it a try. If you do, please report any problems you find and enhancement requests in the GitHub issue tracker.

This isn’t really the correct thread for Bean Validation problems, a new thread would have been more appropriate.

I would venture to guess that you have the Bean Validation API only on your compilation classpath but not deployed to the server, and your server does not have an implementation of the API as a shared library either. Note that if the server does not have such an implementation, you also need to deploy an implementation with your application, not only the API JARs. All this should be doable in your ivy.xml or pom.xml with correct dependencies and scopes/ivy configurations.

Thanks a lot, Henri, I will try it next week and provide feedback then.

Sorry, it took me a bit longer to get a chance to try the ExtensibleBeanContainer. Now I did and it works fine for me. I use it like BeanItemContainer, (bean as ID), and I can’t find a problem so far.
I wouldn’t mind to find this in a future Vaadin release. :slight_smile:

Thanks again!

Is there anybody who implemented ‘addNestedContainerProperty’ in ExtensibleBeanContainer? Seems to work not correctly. Properties of baseclass were set, properties of subclass weren’t.
Or is there another solution?