You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@wicket.apache.org by Dane Laverty <da...@chemeketa.edu> on 2008/10/11 00:21:53 UTC

Downloading a BLOB

The title basically says it all. I've got a BLOB in a database, and I
want the user to be able to click a link and download it. Any wicket
solutions to do this? Thanks much.

 


Re: Downloading a BLOB

Posted by Johan Compagner <jc...@gmail.com>.
Deleting a file right after a first download also has its problems,
My HP network printer/scanner does that, i can scan to an image, but
firefox displayes then that image and what ever i do then to save it
to disk, i get nothing because FF seems to want to get it again for
saving bu hp doesnt serve it anymore, i have to use IE7 for that to
get my scanned image. HP really should do more testing! And serve the
resource differently.

On 10/13/08, Bruno Borges <br...@gmail.com> wrote:
> I think is better to create a temporary file and set DownloadLink to delete
> it after download is complete. I don't think is a good idea to let the user
> download directly from the database as you proposed. See, downloads can take
> some time and letting that InputStream open, might be a problem. The latency
> of an external download is bigger than downloading from a local database.
>
> Cheers,
> Bruno Borges
> blog.brunoborges.com.br
> +55 21 76727099
>
> "The glory of great men should always be
> measured by the means they have used to
> acquire it."
> - Francois de La Rochefoucauld
>
>
> On Fri, Oct 10, 2008 at 10:04 PM, Dane Laverty
> <da...@chemeketa.edu>wrote:
>
>> Thank you for the advice. Here's the solution I came up with, in case
>> it's useful to anyone else.
>>
>> First I used the DownloadLink as a template for my "blobDownloadLink".
>> Then I created an InputStreamResourceStream, which is essentially a
>> barely modified version of Wicket's FileResourceStream, taking an
>> InputStream as the constructor parameter instead of a File. The code for
>> both of those is below.
>>
>> While this solution works, the two issues still hanging in my mind are:
>> 1. I'm sure there's an easier way to get the InputStream into an
>> IResourceStream than to create an InputStreamResourceStream class...I
>> just couldn't figure out what it is.
>> 2. When I get the Blob from the database like this,
>>
>>        rs.getBinaryStream(1);
>>
>> the returned BinaryStream doesn't work. Doing this,
>>
>>        java.sql.Blob blob = rs.getBlob(1);
>>        return blob.getBinaryStream();
>>
>> doesn't work either. So I ended up doing,
>>
>>        java.sql.Blob blob = rs.getBlob(1);
>>        byte[] bytes = new byte[(int)blob.length()];
>>        try {
>>                blob.getBinaryStream().read(bytes);
>>        } catch (IOException ioe) {
>>                // handle it
>>        }
>>        return new ByteArrayInputStream(bytes);
>>
>> Not pretty, but it works.
>>
>> *******
>> // Relevant code for blobDownloadLink
>>
>> Link blobDownloadLink = new Link("blobDownloadLink") {
>>                                @Override
>>                                public void onClick() {
>>                                        InputStream inputStream =
>> //getBlobAsInputStreamFromDatabase();
>>
>>                                        IResourceStream resourceStream =
>> new InputStreamResourceStream(inputStream);
>>
>> getRequestCycle().setRequestTarget(new
>> ResourceStreamRequestTarget(resourceStream)
>>                                        {
>>                                                public String
>> getFileName()
>>                                                {
>>                                                        return
>> //theFileNameYouWantAssociatedWithThisDownload;
>>                                                }
>>
>>                                                public void
>> respond(RequestCycle requestCycle)
>>                                                {
>>
>> super.respond(requestCycle);
>>
>>                                                }
>>                                        });
>>
>>                                        try {
>>                                                inputStream.close();
>>                                        } catch (IOException ioe) {
>>                                                logger.error("Error
>> attempting to close inputStream in blobDownloadLink.", ioe);
>>                                        }
>>                                };
>>                        };
>>
>> ********
>> // Relevant code for InputStreamResourceStream
>>
>> import java.io.IOException;
>> import java.io.InputStream;
>> import org.apache.wicket.util.resource.AbstractResourceStream;
>> import org.apache.wicket.util.resource.ResourceStreamNotFoundException;
>>
>> /**
>>  * An InputStreamResourceStream is an IResource implementation for
>> files.
>>  *
>>  * @see org.apache.wicket.util.resource.IResourceStream
>>  * @see org.apache.wicket.util.watch.IModifiable
>>  * @author Dane Laverty
>>  */
>> public class InputStreamResourceStream extends AbstractResourceStream
>> {
>>        private static final long serialVersionUID = 1L;
>>
>>        /** Resource stream */
>>        private transient InputStream inputStream;
>>
>>        /**
>>         * Constructor.
>>         *
>>         * @param inputStream
>>         *            {@link InputStream} containing resource
>>         */
>>        public InputStreamResourceStream(InputStream inputStream)
>>        {
>>                this.inputStream = inputStream;
>>        }
>>
>>        /**
>>         * Closes this resource.
>>         *
>>         * @throws IOException
>>         */
>>        public void close() throws IOException
>>        {
>>                if (inputStream != null)
>>                {
>>                        inputStream.close();
>>                        inputStream = null;
>>                }
>>        }
>>
>>        /**
>>         * @see IResourceStream#getContentType()
>>         */
>>        public String getContentType()
>>        {
>>                // Let ResourceStreamRequestTarget handle content-type
>> automatically
>>                return null;
>>        }
>>
>>        /**
>>         * @return A readable input stream for this resource. The same
>> input stream is returned until
>>         *         <tt>InputStreamResourceStream.close()</tt> is
>> invoked.
>>         *
>>         * @throws ResourceStreamNotFoundException
>>         */
>>        public InputStream getInputStream() throws
>> ResourceStreamNotFoundException
>>        {
>>                if (inputStream == null)
>>                        throw new
>> ResourceStreamNotFoundException("InputStream could not be found");
>>
>>                return inputStream;
>>         }
>>
>> }
>>
>>
>> -----Original Message-----
>> From: Igor Vaynberg [mailto:igor.vaynberg@gmail.com]
>> Sent: Friday, October 10, 2008 3:37 PM
>> To: users@wicket.apache.org
>> Subject: Re: Downloading a BLOB
>>
>> i didnt say use the downloadlink, i said see how it works...
>>
>> -igor
>>
>> On Fri, Oct 10, 2008 at 3:32 PM, Dane Laverty
>> <da...@chemeketa.edu> wrote:
>> > DownloadLink appears to accept only a file pathname. If I understand
>> it
>> > correctly, the only way I could use that would be to read the BLOB
>> into
>> > a file on the server, and then have the DownloadLink point to that
>> file.
>> > I believe that would require me to have the file created when the page
>> > is generated, rather than when the link is clicked. Since there are
>> > going to be many links on this page, I would rather be able to wait
>> > until the user clicks the link to stream the BLOB to them.
>> >
>> > -----Original Message-----
>> > From: Igor Vaynberg [mailto:igor.vaynberg@gmail.com]
>> > Sent: Friday, October 10, 2008 3:26 PM
>> > To: users@wicket.apache.org
>> > Subject: Re: Downloading a BLOB
>> >
>> > see how downloadlink works
>> >
>> > -igor
>> >
>> > On Fri, Oct 10, 2008 at 3:21 PM, Dane Laverty
>> > <da...@chemeketa.edu> wrote:
>> >> The title basically says it all. I've got a BLOB in a database, and I
>> >> want the user to be able to click a link and download it. Any wicket
>> >> solutions to do this? Thanks much.
>> >>
>> >>
>> >>
>> >>
>> >
>> > ---------------------------------------------------------------------
>> > To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
>> > For additional commands, e-mail: users-help@wicket.apache.org
>> >
>> >
>> > ---------------------------------------------------------------------
>> > To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
>> > For additional commands, e-mail: users-help@wicket.apache.org
>> >
>> >
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
>> For additional commands, e-mail: users-help@wicket.apache.org
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
>> For additional commands, e-mail: users-help@wicket.apache.org
>>
>>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: Downloading a BLOB

Posted by Bruno Borges <br...@gmail.com>.
I think is better to create a temporary file and set DownloadLink to delete
it after download is complete. I don't think is a good idea to let the user
download directly from the database as you proposed. See, downloads can take
some time and letting that InputStream open, might be a problem. The latency
of an external download is bigger than downloading from a local database.

Cheers,
Bruno Borges
blog.brunoborges.com.br
+55 21 76727099

"The glory of great men should always be
measured by the means they have used to
acquire it."
- Francois de La Rochefoucauld


On Fri, Oct 10, 2008 at 10:04 PM, Dane Laverty <da...@chemeketa.edu>wrote:

> Thank you for the advice. Here's the solution I came up with, in case
> it's useful to anyone else.
>
> First I used the DownloadLink as a template for my "blobDownloadLink".
> Then I created an InputStreamResourceStream, which is essentially a
> barely modified version of Wicket's FileResourceStream, taking an
> InputStream as the constructor parameter instead of a File. The code for
> both of those is below.
>
> While this solution works, the two issues still hanging in my mind are:
> 1. I'm sure there's an easier way to get the InputStream into an
> IResourceStream than to create an InputStreamResourceStream class...I
> just couldn't figure out what it is.
> 2. When I get the Blob from the database like this,
>
>        rs.getBinaryStream(1);
>
> the returned BinaryStream doesn't work. Doing this,
>
>        java.sql.Blob blob = rs.getBlob(1);
>        return blob.getBinaryStream();
>
> doesn't work either. So I ended up doing,
>
>        java.sql.Blob blob = rs.getBlob(1);
>        byte[] bytes = new byte[(int)blob.length()];
>        try {
>                blob.getBinaryStream().read(bytes);
>        } catch (IOException ioe) {
>                // handle it
>        }
>        return new ByteArrayInputStream(bytes);
>
> Not pretty, but it works.
>
> *******
> // Relevant code for blobDownloadLink
>
> Link blobDownloadLink = new Link("blobDownloadLink") {
>                                @Override
>                                public void onClick() {
>                                        InputStream inputStream =
> //getBlobAsInputStreamFromDatabase();
>
>                                        IResourceStream resourceStream =
> new InputStreamResourceStream(inputStream);
>
> getRequestCycle().setRequestTarget(new
> ResourceStreamRequestTarget(resourceStream)
>                                        {
>                                                public String
> getFileName()
>                                                {
>                                                        return
> //theFileNameYouWantAssociatedWithThisDownload;
>                                                }
>
>                                                public void
> respond(RequestCycle requestCycle)
>                                                {
>
> super.respond(requestCycle);
>
>                                                }
>                                        });
>
>                                        try {
>                                                inputStream.close();
>                                        } catch (IOException ioe) {
>                                                logger.error("Error
> attempting to close inputStream in blobDownloadLink.", ioe);
>                                        }
>                                };
>                        };
>
> ********
> // Relevant code for InputStreamResourceStream
>
> import java.io.IOException;
> import java.io.InputStream;
> import org.apache.wicket.util.resource.AbstractResourceStream;
> import org.apache.wicket.util.resource.ResourceStreamNotFoundException;
>
> /**
>  * An InputStreamResourceStream is an IResource implementation for
> files.
>  *
>  * @see org.apache.wicket.util.resource.IResourceStream
>  * @see org.apache.wicket.util.watch.IModifiable
>  * @author Dane Laverty
>  */
> public class InputStreamResourceStream extends AbstractResourceStream
> {
>        private static final long serialVersionUID = 1L;
>
>        /** Resource stream */
>        private transient InputStream inputStream;
>
>        /**
>         * Constructor.
>         *
>         * @param inputStream
>         *            {@link InputStream} containing resource
>         */
>        public InputStreamResourceStream(InputStream inputStream)
>        {
>                this.inputStream = inputStream;
>        }
>
>        /**
>         * Closes this resource.
>         *
>         * @throws IOException
>         */
>        public void close() throws IOException
>        {
>                if (inputStream != null)
>                {
>                        inputStream.close();
>                        inputStream = null;
>                }
>        }
>
>        /**
>         * @see IResourceStream#getContentType()
>         */
>        public String getContentType()
>        {
>                // Let ResourceStreamRequestTarget handle content-type
> automatically
>                return null;
>        }
>
>        /**
>         * @return A readable input stream for this resource. The same
> input stream is returned until
>         *         <tt>InputStreamResourceStream.close()</tt> is
> invoked.
>         *
>         * @throws ResourceStreamNotFoundException
>         */
>        public InputStream getInputStream() throws
> ResourceStreamNotFoundException
>        {
>                if (inputStream == null)
>                        throw new
> ResourceStreamNotFoundException("InputStream could not be found");
>
>                return inputStream;
>         }
>
> }
>
>
> -----Original Message-----
> From: Igor Vaynberg [mailto:igor.vaynberg@gmail.com]
> Sent: Friday, October 10, 2008 3:37 PM
> To: users@wicket.apache.org
> Subject: Re: Downloading a BLOB
>
> i didnt say use the downloadlink, i said see how it works...
>
> -igor
>
> On Fri, Oct 10, 2008 at 3:32 PM, Dane Laverty
> <da...@chemeketa.edu> wrote:
> > DownloadLink appears to accept only a file pathname. If I understand
> it
> > correctly, the only way I could use that would be to read the BLOB
> into
> > a file on the server, and then have the DownloadLink point to that
> file.
> > I believe that would require me to have the file created when the page
> > is generated, rather than when the link is clicked. Since there are
> > going to be many links on this page, I would rather be able to wait
> > until the user clicks the link to stream the BLOB to them.
> >
> > -----Original Message-----
> > From: Igor Vaynberg [mailto:igor.vaynberg@gmail.com]
> > Sent: Friday, October 10, 2008 3:26 PM
> > To: users@wicket.apache.org
> > Subject: Re: Downloading a BLOB
> >
> > see how downloadlink works
> >
> > -igor
> >
> > On Fri, Oct 10, 2008 at 3:21 PM, Dane Laverty
> > <da...@chemeketa.edu> wrote:
> >> The title basically says it all. I've got a BLOB in a database, and I
> >> want the user to be able to click a link and download it. Any wicket
> >> solutions to do this? Thanks much.
> >>
> >>
> >>
> >>
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> > For additional commands, e-mail: users-help@wicket.apache.org
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> > For additional commands, e-mail: users-help@wicket.apache.org
> >
> >
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>
>

RE: Downloading a BLOB

Posted by Dane Laverty <da...@chemeketa.edu>.
Thank you for the advice. Here's the solution I came up with, in case
it's useful to anyone else.

First I used the DownloadLink as a template for my "blobDownloadLink".
Then I created an InputStreamResourceStream, which is essentially a
barely modified version of Wicket's FileResourceStream, taking an
InputStream as the constructor parameter instead of a File. The code for
both of those is below.

While this solution works, the two issues still hanging in my mind are:
1. I'm sure there's an easier way to get the InputStream into an
IResourceStream than to create an InputStreamResourceStream class...I
just couldn't figure out what it is.
2. When I get the Blob from the database like this, 

	rs.getBinaryStream(1);

the returned BinaryStream doesn't work. Doing this,

	java.sql.Blob blob = rs.getBlob(1);
	return blob.getBinaryStream();

doesn't work either. So I ended up doing,

	java.sql.Blob blob = rs.getBlob(1);
	byte[] bytes = new byte[(int)blob.length()];
	try {
		blob.getBinaryStream().read(bytes);
	} catch (IOException ioe) {
		// handle it
	}
	return new ByteArrayInputStream(bytes);

Not pretty, but it works.

*******
// Relevant code for blobDownloadLink

Link blobDownloadLink = new Link("blobDownloadLink") {
        			@Override
        			public void onClick() {
        				InputStream inputStream =
//getBlobAsInputStreamFromDatabase();
        				
        				IResourceStream resourceStream =
new InputStreamResourceStream(inputStream);
 
getRequestCycle().setRequestTarget(new
ResourceStreamRequestTarget(resourceStream)
        				{
        					public String
getFileName()
        					{
        						return
//theFileNameYouWantAssociatedWithThisDownload;
        					}

        					public void
respond(RequestCycle requestCycle)
        					{
 
super.respond(requestCycle);

        					}
        				});
        				
        				try {
        					inputStream.close();
        				} catch (IOException ioe) {
        					logger.error("Error
attempting to close inputStream in blobDownloadLink.", ioe);
        				}
        			};
        		};

********
// Relevant code for InputStreamResourceStream

import java.io.IOException;
import java.io.InputStream;
import org.apache.wicket.util.resource.AbstractResourceStream;
import org.apache.wicket.util.resource.ResourceStreamNotFoundException;

/**
 * An InputStreamResourceStream is an IResource implementation for
files.
 * 
 * @see org.apache.wicket.util.resource.IResourceStream
 * @see org.apache.wicket.util.watch.IModifiable
 * @author Dane Laverty
 */
public class InputStreamResourceStream extends AbstractResourceStream
{
	private static final long serialVersionUID = 1L;

	/** Resource stream */
	private transient InputStream inputStream;

	/**
	 * Constructor.
	 * 
	 * @param inputStream
	 *            {@link InputStream} containing resource
	 */
	public InputStreamResourceStream(InputStream inputStream)
	{
		this.inputStream = inputStream;
	}

	/**
	 * Closes this resource.
	 * 
	 * @throws IOException
	 */
	public void close() throws IOException
	{
		if (inputStream != null)
		{
			inputStream.close();
			inputStream = null;
		}
	}

	/**
	 * @see IResourceStream#getContentType()
	 */
	public String getContentType()
	{
		// Let ResourceStreamRequestTarget handle content-type
automatically
		return null;
	}

	/**
	 * @return A readable input stream for this resource. The same
input stream is returned until
	 *         <tt>InputStreamResourceStream.close()</tt> is
invoked.
	 * 
	 * @throws ResourceStreamNotFoundException
	 */
	public InputStream getInputStream() throws
ResourceStreamNotFoundException
	{
		if (inputStream == null)
			throw new
ResourceStreamNotFoundException("InputStream could not be found");

		return inputStream;
	}

}
	

-----Original Message-----
From: Igor Vaynberg [mailto:igor.vaynberg@gmail.com] 
Sent: Friday, October 10, 2008 3:37 PM
To: users@wicket.apache.org
Subject: Re: Downloading a BLOB

i didnt say use the downloadlink, i said see how it works...

-igor

On Fri, Oct 10, 2008 at 3:32 PM, Dane Laverty
<da...@chemeketa.edu> wrote:
> DownloadLink appears to accept only a file pathname. If I understand
it
> correctly, the only way I could use that would be to read the BLOB
into
> a file on the server, and then have the DownloadLink point to that
file.
> I believe that would require me to have the file created when the page
> is generated, rather than when the link is clicked. Since there are
> going to be many links on this page, I would rather be able to wait
> until the user clicks the link to stream the BLOB to them.
>
> -----Original Message-----
> From: Igor Vaynberg [mailto:igor.vaynberg@gmail.com]
> Sent: Friday, October 10, 2008 3:26 PM
> To: users@wicket.apache.org
> Subject: Re: Downloading a BLOB
>
> see how downloadlink works
>
> -igor
>
> On Fri, Oct 10, 2008 at 3:21 PM, Dane Laverty
> <da...@chemeketa.edu> wrote:
>> The title basically says it all. I've got a BLOB in a database, and I
>> want the user to be able to click a link and download it. Any wicket
>> solutions to do this? Thanks much.
>>
>>
>>
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: Downloading a BLOB

Posted by Igor Vaynberg <ig...@gmail.com>.
i didnt say use the downloadlink, i said see how it works...

-igor

On Fri, Oct 10, 2008 at 3:32 PM, Dane Laverty <da...@chemeketa.edu> wrote:
> DownloadLink appears to accept only a file pathname. If I understand it
> correctly, the only way I could use that would be to read the BLOB into
> a file on the server, and then have the DownloadLink point to that file.
> I believe that would require me to have the file created when the page
> is generated, rather than when the link is clicked. Since there are
> going to be many links on this page, I would rather be able to wait
> until the user clicks the link to stream the BLOB to them.
>
> -----Original Message-----
> From: Igor Vaynberg [mailto:igor.vaynberg@gmail.com]
> Sent: Friday, October 10, 2008 3:26 PM
> To: users@wicket.apache.org
> Subject: Re: Downloading a BLOB
>
> see how downloadlink works
>
> -igor
>
> On Fri, Oct 10, 2008 at 3:21 PM, Dane Laverty
> <da...@chemeketa.edu> wrote:
>> The title basically says it all. I've got a BLOB in a database, and I
>> want the user to be able to click a link and download it. Any wicket
>> solutions to do this? Thanks much.
>>
>>
>>
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


RE: Downloading a BLOB

Posted by Dane Laverty <da...@chemeketa.edu>.
DownloadLink appears to accept only a file pathname. If I understand it
correctly, the only way I could use that would be to read the BLOB into
a file on the server, and then have the DownloadLink point to that file.
I believe that would require me to have the file created when the page
is generated, rather than when the link is clicked. Since there are
going to be many links on this page, I would rather be able to wait
until the user clicks the link to stream the BLOB to them. 

-----Original Message-----
From: Igor Vaynberg [mailto:igor.vaynberg@gmail.com] 
Sent: Friday, October 10, 2008 3:26 PM
To: users@wicket.apache.org
Subject: Re: Downloading a BLOB

see how downloadlink works

-igor

On Fri, Oct 10, 2008 at 3:21 PM, Dane Laverty
<da...@chemeketa.edu> wrote:
> The title basically says it all. I've got a BLOB in a database, and I
> want the user to be able to click a link and download it. Any wicket
> solutions to do this? Thanks much.
>
>
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: Downloading a BLOB

Posted by Igor Vaynberg <ig...@gmail.com>.
see how downloadlink works

-igor

On Fri, Oct 10, 2008 at 3:21 PM, Dane Laverty <da...@chemeketa.edu> wrote:
> The title basically says it all. I've got a BLOB in a database, and I
> want the user to be able to click a link and download it. Any wicket
> solutions to do this? Thanks much.
>
>
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org