I would suggest replacing in your Pojo the Image instance with a simple byte[], because looking through the UploadField code, I can't see any natural way of converting the result from the upload (which is either a byte[] or a File instance) into something else, using the FieldGroup like you asked.
If you look inside AbstractField.getValue(), you will see that the model value is eventually passed through a settable converter which would have normally helped you in this case (see com.vaadin.data.util.converter.Converter). But I think you are pretty much forced to use byte[] if you want to bind a image bean to the FieldGroup.
Anyway, if you DO replace with byte[] the following steps will help you:
Create a custom FieldGroupFieldFactory that will create an UploadField if you want to bind to a byte[] property + passes a ValueChangeListener for the UploadField is done uploading:
public class ImageEnhancedFieldFactory extends DefaultFieldGroupFieldFactory {
private Property.ValueChangeListener fileUploadedListener; private ImageEnhancedFieldFactory(Property.ValueChangeListener fileUploadedListener) { this.fileUploadedListener = fileUploadedListener; } @Override public <T extends Field> T createField(Class<?> type, Class<T> fieldType) { if (byte[].class.equals(type)) { UploadField uploadField = new UploadField(UploadField.StorageMode.MEMORY); uploadField.setFieldType(UploadField.FieldType.BYTE_ARRAY); uploadField.setButtonCaption("Change image"); uploadField.addListener(fileUploadedListener); return (T) uploadField; } return super.createField(type, fieldType); }
}
Create an Image instance that shows the content of the byte[] from the pojo:
final ImagePojo imagePojo = new ImagePojo(); imagePojo.setName("superman"); imagePojo.setImageContent(new byte[0]); BeanItem<ImagePojo> item = new BeanItem<ImagePojo>(imagePojo); final StreamResource imageResource = new StreamResource(new StreamResource.StreamSource() { @Override public InputStream getStream() { return new ByteArrayInputStream(imagePojo.getImageContent()); } }, "myimage"); imageResource.setCacheTime(0); final Image image = new Image("Image", imageResource); addComponent(image);
NOTE: its necessary to set the cache time to 0 in order to prevent the browser from caching the resource( see https://vaadin.com/book/vaadin7/-/page/components.embedded.html in the section Generating and Reloading Images)
3.Create the FieldGroup (with the new FieldGroupFieldFactory set) and bind to the properties of the pojo, including the one that contains the image content (the byte[]):
FieldGroup fieldGroup = new FieldGroup(item);
fieldGroup.setFieldFactory(new ImageEnhancedFieldFactory(new Property.ValueChangeListener() {
@Override
public void valueChange(Property.ValueChangeEvent event) {
SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmssSSS");
String filename = "myfilename-" + df.format(new Date()) + ".jpg";
imagePojo.setImageContent((byte[])event.getProperty().getValue());
image.markAsDirty();
imageResource.setFilename(filename);
}
}));
addComponent(fieldGroup.buildAndBind("Image name", "name"));
addComponent(fieldGroup.buildAndBind("Image content", "imageContent"));
I left a snippet on Gist of a component that you can paste in you UI and play around if you need (https://gist.github.com/gabrielruiu/9953279)