You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by Christopher Dodunski <Ch...@christopher.net.nz> on 2017/11/03 00:40:09 UTC

How to display a Blob (byte[]) from database in a Tapestry template

Hi all,

I am having a little difficulty with what I imagine is a very common use
case: displaying a user's profile image alongside their personal details
following successful login.  Displaying the JavaBean strings served up by
Hibernate is easy.  Just displaying the database Blob (stored as a byte
array in the JavaBean entity) is proving more challenging.


[Welcome.tml]

    ...
    <div>
        <img src="${imageLink}" />
        <strong>${user.firstName} ${user.lastName}</strong><br/>
        User name: "${user.userName}"<br/>
        E-mail: ${user.email}<br/>
    </div>
    ...


[Welcome.java]

    ...
    public void onActivate(){
        user = authenticator.getLoggedUser();

        company = user.getCompany();

        ports = company.getPorts();
    }


    public Link getImageLink(){
        return pageLink.createPageRenderLinkWithContext(BlobImage.class,
user.getImage());
    }
    ...


[BlobImage.java]

package com.example.harbour.pages;

import org.apache.tapestry5.StreamResponse;
import org.apache.tapestry5.services.Response;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * Class created for displaying Blob (profile) images read from the
database, as per the below howto:
 *
https://stackoverflow.com/questions/13213236/tapestry-display-blob-using-markup
 */
public class BlobImage {

    public StreamResponse onActivate(byte[] byteArray){

        //Retrieve your image using the context parameter(s)
        final InputStream imageStream = new ByteArrayInputStream(byteArray);

        return new StreamResponse(){

            @Override
            public InputStream getStream() throws IOException {
                return imageStream;
            }

            @Override
            String getContentType(){
                return "image/png";
            }

            @Override
            void prepareResponse(Response response){}
        };
    }
}


[The Compilation Error]

[ERROR] Failed to execute goal
org.apache.maven.plugins:maven-compiler-plugin:2.3.2:compile
(default-compile) on project harbour: Compilation failure: Compilation
failure:
[ERROR]
\Users\Setup\Desktop\IdeaProjects\Harbour\src\main\java\com\example\harbour\pages\BlobImage.java:[37,17]
error: prepareResponse(Response) in <anonymous
com.example.harbour.pages.BlobImage$1> cannot implement
prepareResponse(Response) in StreamResponse
[ERROR]
\Users\Setup\Desktop\IdeaProjects\Harbour\src\main\java\com\example\harbour\pages\BlobImage.java:[32,19]
error: getContentType() in <anonymous
com.example.harbour.pages.BlobImage$1> cannot implement getContentType()
in StreamResponse


Is creating a separate image streaming class, like above, the best way of
displaying a database image in a Tapestry 5 template, as the 'howto' I
followed is 5+ years' old now?  I couldn't find any newer examples on the
Tapestry website.

Thanks for your assistance,

Chris.


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


Re: How to display a Blob (byte[]) from database in a Tapestry template

Posted by Cezary Biernacki <ce...@gmail.com>.
Hi,
first you have a compilation problem related to basic Java: methods
getContentType()
and prepareResponse() should be public as they are required by
StreamResponse interface - it is what the compiler complains about.

However the second problem is that BlobImage.onActivate() should not
require a byte array as input argument. onActivate() parameters are
retrieved from a request URL, so basically in your implementation BlobImage
would expect whole image encoded in URL and just send back it. Instead you
should rather expect user id, and retrieve the image from the database
inside BlobImage, and in getImageLink() the context should be a user, not
the whole image. BTW, You might consider setting some response parameters
to control image caching by user's browsers, but it is an optimisation.

On the other hand, if images are small, and you want to avoid reading data
twice from the database, you might remove BlobImage, and just encode the
image directly as a data URI. E.g.:

 public String getImageLink(){
        return "data:image/png;base64," +
Base64.getUrlEncoder().encodeToString(user.getImage());
    }



On Fri, Nov 3, 2017 at 1:40 AM, Christopher Dodunski <
ChrisFromTapestry@christopher.net.nz> wrote:

> Hi all,
>
> I am having a little difficulty with what I imagine is a very common use
> case: displaying a user's profile image alongside their personal details
> following successful login.  Displaying the JavaBean strings served up by
> Hibernate is easy.  Just displaying the database Blob (stored as a byte
> array in the JavaBean entity) is proving more challenging.
>
>
> [Welcome.tml]
>
>     ...
>     <div>
>         <img src="${imageLink}" />
>         <strong>${user.firstName} ${user.lastName}</strong><br/>
>         User name: "${user.userName}"<br/>
>         E-mail: ${user.email}<br/>
>     </div>
>     ...
>
>
> [Welcome.java]
>
>     ...
>     public void onActivate(){
>         user = authenticator.getLoggedUser();
>
>         company = user.getCompany();
>
>         ports = company.getPorts();
>     }
>
>
>     public Link getImageLink(){
>         return pageLink.createPageRenderLinkWithContext(BlobImage.class,
> user.getImage());
>     }
>     ...
>
>
> [BlobImage.java]
>
> package com.example.harbour.pages;
>
> import org.apache.tapestry5.StreamResponse;
> import org.apache.tapestry5.services.Response;
>
> import java.io.ByteArrayInputStream;
> import java.io.IOException;
> import java.io.InputStream;
>
> /**
>  * Class created for displaying Blob (profile) images read from the
> database, as per the below howto:
>  *
> https://stackoverflow.com/questions/13213236/tapestry-
> display-blob-using-markup
>  */
> public class BlobImage {
>
>     public StreamResponse onActivate(byte[] byteArray){
>
>         //Retrieve your image using the context parameter(s)
>         final InputStream imageStream = new ByteArrayInputStream(
> byteArray);
>
>         return new StreamResponse(){
>
>             @Override
>             public InputStream getStream() throws IOException {
>                 return imageStream;
>             }
>
>             @Override
>             String getContentType(){
>                 return "image/png";
>             }
>
>             @Override
>             void prepareResponse(Response response){}
>         };
>     }
> }
>
>
> [The Compilation Error]
>
> [ERROR] Failed to execute goal
> org.apache.maven.plugins:maven-compiler-plugin:2.3.2:compile
> (default-compile) on project harbour: Compilation failure: Compilation
> failure:
> [ERROR]
> \Users\Setup\Desktop\IdeaProjects\Harbour\src\main\
> java\com\example\harbour\pages\BlobImage.java:[37,17]
> error: prepareResponse(Response) in <anonymous
> com.example.harbour.pages.BlobImage$1> cannot implement
> prepareResponse(Response) in StreamResponse
> [ERROR]
> \Users\Setup\Desktop\IdeaProjects\Harbour\src\main\
> java\com\example\harbour\pages\BlobImage.java:[32,19]
> error: getContentType() in <anonymous
> com.example.harbour.pages.BlobImage$1> cannot implement getContentType()
> in StreamResponse
>
>
> Is creating a separate image streaming class, like above, the best way of
> displaying a database image in a Tapestry 5 template, as the 'howto' I
> followed is 5+ years' old now?  I couldn't find any newer examples on the
> Tapestry website.
>
> Thanks for your assistance,
>
> Chris.
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
>
>