Over a million developers have joined DZone.

Image Upload Using TinyMCE Within Wicket Framework

DZone's Guide to

Image Upload Using TinyMCE Within Wicket Framework

· Java Zone
Free Resource

Bitbucket is for the code that takes us to Mars, decodes the human genome, or drives your next car. What will your code do? Get started with Bitbucket today, it's free.

The goal of this article is to show how to upload images using tinymce within wicket framework. My intension was to show how to do this using only wicket's without additional servlets, tinymce html dialogs, etc. Everything from the begining to the end is done with witckets and little of java script which tiny needs.  I assume that people who will read this article have knowledge about wicket framework and have integrated tinymce from wicketstuff-core with their project. This functionality can be divided into three parts: creating a tinymce plugin, creating wicket dialog and inserting newly created image into tiny editor.

Creating a plugin:

To do this we need to create a java script file and corresponding plugin java file. Java script file must be named editor_plugin_src.js and must be placed in resources in package which name starts with wicket.contrib.tinymce.tiny_mce.plugins . So in our case I created in src/main/resources a package wicket.contrib.tinymce.tiny_mce.plugins.imageupload and put there a java script which looks like this:

(function() {
tinymce.create('tinymce.plugins.ImageUpload', {
init : function(ed, url) {
var t = this;
t.editor = ed;
// Register command
ed.addCommand('mceImageUpload', t._showDialog, t);
// Register button
ed.addButton('upload', {title : 'Upload image', cmd : 'mceImageUpload'});
_showDialog : function() {
var ed = this.editor;
// Register plugin
tinymce.PluginManager.add('imageupload', tinymce.plugins.ImageUpload);

It's a standard look of almost all plugins. Thing we are most interested in is a _showDialog function which will execute callback for opening wicket dialog. But before we will define the callback we must create a Java plugin.

Java plugin:

    public class ImageUploadPlugin extends Plugin {

private PluginButton imageUploadButton;

public ImageUploadPlugin() {
imageUploadButton = new PluginButton("upload", this);

public PluginButton getImageUploadButton() {
return imageUploadButton;

To show our plugin in tiny we just need to add it to tiny settings.

ImageUploadPlugin imageUploadPlugin = new ImageUploadPlugin();
settings.add(imageUploadPlugin.getImageUploadButton(), TinyMCESettings.Toolbar.first, TinyMCESettings.Position.after);

Ok so we have a button placed in tiny. Now we need to create Wicket Behavior which will respond on our button click.

public class ImageUploadBehavior extends AbstractDefaultAjaxBehavior {

protected void respond(AjaxRequestTarget pTarget) {
//place show dialog logic here

public String getFunctionName() {
return "showImageUploadDialog";

public void renderHead(IHeaderResponse pResponse) {
String script = getFunctionName() + " = function () { "
+ getCallbackScript() + " }";

Behavior places the generated callback to itself in body of showImageUploadDialog function. This function will be rendered right after the DOM is build. Now, we have to bind functiom name to the button. We will do this by overriding definePluginSettings method in ImageUploadPlugin.

protected void definePluginSettings(StringBuffer pBuffer) {
pBuffer.append(",\n\tuploadimage_callback: \"" + imageUploadBehavior.getFunctionName() + "\"");

Now the callback which bounds into our function must be executed on button click. So in editor_plugin_src.js to  _showDialog() function we are adding:

ed.execCallback('uploadimage_callback', ed);

That's it. Our button is bound with ImageUploadBehavior. Since behavior does not work without component we need to add this behavior to panel, we will do it in the next step.

Creating a dialog:

We need a wicket modal window with simple content for adding images (input type file + ajax submit button). To create a modal window we need to place it in the panel. So we are creating a panel and at once we are adding our behavior to it. I will also place here ImageUploadBehavior.class and ImageUploadPlugin.class.

public class ImageUploadPanel extends Panel  {
private ModalWindow modalWindow;

public ImageUploadPanel(String pId) {
add(modalWindow = new ModalWindow("imageUploadDialog"));
modalWindow.setTitle(new ResourceModel("title.label"));

add(imageUploadBehavior = new ImageUploadBehavior());

public class ImageUploadBehavior …

public class ImageUploadPlugin …

with the corresponding markup:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org/">
<div wicket:id="imageUploadDialog"></div>

and properties file:
title.label=Upload image

Modal window with title and initial height and width is created. Now we will create panel for uploading images which will be placed inside our modal window. We will create a form with FileUploadField and AjaxButton for submiting a form and a Feedback panel which will display error when something goes wrong.

public class ImageUploadContentPanel extends Panel {
public ImageUploadContentPanel(String pId) {
Form<?> form = new Form<Void>("form");
final FeedbackPanel feedback = new FeedbackPanel("feedback");
final FileUploadField fileUploadField = new FileUploadField("file");
fileUploadField.setLabel(new ResourceModel("required.label"));
form.add(new AjaxButton("uploadButton", form) {

protected void onSubmit(AjaxRequestTarget pTarget, Form<?> pForm) {
protected void onError(AjaxRequestTarget pTarget, Form<?> pForm) {

* Method invoked after image upload.
* @param pTarget - ajax target
* @param pImageName - image name
* @param pContentType – image content type
public void onImageUploaded(String pImageName, String pContentType, AjaxRequestTarget pTarget) {}

with the corresponding markup:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org/">
<form wicket:id="form">
<input wicket:id="file" type="file"/>
<button wicket:id="uploadButton" type="button">
<wicket:message key="upload.button.label"/>
<span class="error" wicket:id="feedback"/>

and properties file:
required.label=Image upload

We can also add a validator which will check if uploaded files are images.

public static class FileExtensionValidator implements IValidator<FileUpload>  {
private static final long serialVersionUID = -8116224338791429342L;
public static final List<String> extensions = Arrays.asList(
public void validate(IValidatable<FileUpload> pValidatable) {
FileUpload image = pValidatable.getValue();
String extension = StringUtils.getFilenameExtension(
if (extension!=null && !extensions.contains(
extension.toLowerCase())) {
ValidationError error = new ValidationError();
error.setVariable("extensions", extensions.toString());


property to UploadConentPanel.properties
WrongExtensionValidator=Invalid file type. Allowes file types are : ${extensions}

and we must add it to FileUploadField

fileUploadField.add(new FileExtensionValidator()); 

Now we need to add this panel as a content to our modal window and show it from behaviour. So we are implementing respond method in our behavior.

protected void respond(AjaxRequestTarget pTarget) {
ImageUploadContentPanel content = new ImageUploadContentPanel(modalWindow.getContentId()) {

So in summary to this section - now we have our panel showed when tiny button is clicked. Last thing we must do is to show uploaded image inside tiny editor.

Inserting image into editor:

Before placing image inside editor we must upload image into some temporary directory. To do this we must implement onSubmit method from AjaxButton which is inside our ImageUploadContentPanel.

protected void onSubmit(AjaxRequestTarget pTarget, Form<?> pForm) {
FileUpload fileUpload = fileUploadField.getFileUpload();
String fileName = fileUpload.getClientFileName();
try {
File currentEngineerDir = new File(getTemporaryDirPath());
fileUpload.writeTo(new File(currentEngineerDir, fileName));
} catch (IOException ex) {
ImageUploadContentPanel.this.error("Can't upload image");
} finally {
onImageUploaded(fileName, fileUpload.getContentType(), pTarget);

Path to our directory will be placed in servlet context temp dir + sessionId.

public String getTemporaryDirPath() {
ServletContext servletContext =WebApplication.get().getServletContext();
return ((File)servletContext.getAttribute("javax.servlet.context.tempdir")).getPath() +
File.separatorChar + Session.get().getId() + File.separatorChar;

Please remember to delete those temporary images when session is invalidated.

Here comes the most tricky part. As I said in the beginning we want to do everything with wickets so we will create img tag and generate src attribute with wicket component path. Url is generated from component instance -> urlFor method. It takes as parameter RequestListenerInterface or ResourceReference. Since our images are dynamic we will choose first solution.We will do it in our ImageUploadPanel but first we need to transfer image name and image content type from our modal content panel to ImageUploadPanel. I did it already by defining  onImageUploaded method. So we just need to override it and create there our img tag (we can also close our modal window).

ImageUploadContentPanel content = new ImageUploadContentPanel(modalWindow.getContentId()) {
                public void onImageUploaded(String pImageName, String pContentType, AjaxRequestTarget pTarget) {
                   XmlTag xmlImageTag = createImageTag(pImageName, pContentType);
		   // TODO inject tag into editor

    public XmlTag createImageTag(String pImageName, String pContentType) {
        XmlTag tag = new XmlTag();
        CharSequence url = ImageUploadPanel.this.urlFor(IResourceListener.INTERFACE);
        StringBuilder sb = new StringBuilder(url);
        tag.put("src", RequestCycle.get().getOriginalResponse().encodeURL(
                Strings.replaceAll(sb.toString(), "&", "&")));
        return tag;


public static final String IMAGE_FILE_NAME = "filename";
public static final String IMAGE_CONTENT_TYPE = "contentType";

Those parameters which are added to url are needed for finding correct image.

So we have url which points to our panel but if we want to listen for requests regarding resources, we must implement IResourceListener. In implementation we must invoke onResourceRequested() method on Resource which we will create. Wickets will do the rest ;)


public class ImageUploadPanel extends Panel implements IResourceListener …

public void onResourceRequested() {
final String fileName = RequestCycle.get().getRequest().getParameter(
final String contentType = RequestCycle.get().getRequest().getParameter(
Resource resource = new Resource() {
public IResourceStream getResourceStream() {
FileInputStream inputStream = null;
try {
inputStream = new FileInputStream(getTemporaryDirPath() +"/"+fileName);
} catch(FileNotFoundException ex) {
throw new RuntimeException("Problem with getting image");
return new FileResourceStream(contentType, inputStream);


public class FileResourceStream extends AbstractResourceStream {

private String contentType;
private InputStream image;

public FileResourceStream(String pContentType, InputStream pImage){
this.image = pImage;
this.contentType = pContentType;

public String getContentType() {
return contentType;

public InputStream getInputStream() throws ResourceStreamNotFoundException {
return image;

public void close() throws IOException {

One thing that's left is injecting generated img into tiny editor. This must be done by java script. So in onImageUploaded method we add:

pTarget.appendJavascript("tinyMCE.execCommand('mceInsertContent', false, '"+xmlImageTag.toString()+"');");

And that's all.

I tested it with Wicket 1.4.7 and FireFox.

Bitbucket is the Git solution for professional teams who code with a purpose, not just as a hobby. Get started today, it's free.


Opinions expressed by DZone contributors are their own.


Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.


{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}