0

I am trying to read an image from a MySQL table The image is defined as a longblob and I am using Eclipse Juno (updated), Java, and GWT (latest version). However, when I run I get error messages on the page (my first view is not displayed):

onModuleLoad() threw an exception


Exception while loading module org.AwardTracker.client.AwardTracker. See Development Mode for details.
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.google.gwt.dev.shell.ModuleSpace.onLoad(ModuleSpace.java:406)
at com.google.gwt.dev.shell.OophmSessionHandler.loadModule(OophmSessionHandler.java:200)
at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:526)
at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:364)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.RuntimeException: Deferred binding failed for 'org.AwardTracker.client.DBConnection' (did you forget to inherit a required module?)
at com.google.gwt.dev.shell.GWTBridgeImpl.create(GWTBridgeImpl.java:53)
at com.google.gwt.core.shared.GWT.create(GWT.java:57)
at com.google.gwt.core.client.GWT.create(GWT.java:85)
at org.AwardTracker.client.LoginView.<init>(LoginView.java:29)
at org.AwardTracker.client.AwardTracker.onModuleLoad(AwardTracker.java:14)
... 9 more
Caused by: com.google.gwt.core.ext.UnableToCompleteException: (see previous log entries)
at com.google.gwt.dev.shell.ModuleSpace.rebind(ModuleSpace.java:605)
at com.google.gwt.dev.shell.ModuleSpace.rebindAndCreate(ModuleSpace.java:465)
at com.google.gwt.dev.shell.GWTBridgeImpl.create(GWTBridgeImpl.java:49)
... 13 more

The Development Console has the following messages (first few lines):

[DEBUG] [org.AwardTracker.AwardTracker] - Validating units:
[INFO] [org.AwardTracker.AwardTracker] - Ignored 4 units with compilation errors in first pass.
Compile with -strict or with -logLevel set to TRACE or DEBUG to see all errors.
[ERROR] [org.AwardTracker.AwardTracker] - Errors in 'file:/C:/Users/Glyndwr/Eclipse/Workspace/AwardTracker/src/org/AwardTracker/client/DBConnection.java'
[ERROR] [org.AwardTracker.AwardTracker] - Line 15: No source code is available for type java.sql.Blob; did you forget to inherit a required module?

My DBConnection is:

package org.AwardTracker.client;

import java.util.List;
import java.sql.Blob;

import com.google.gwt.user.client.rpc.RemoteService;

/**
 * The client side stub for the RPC service.
 */
public interface DBConnection extends RemoteService {
public User authenticateUser(String user, String pass, String level, String archived);
public User duplicateUser(String user, String pass, String level, String archived);
public User createUser(String user, String pass, String level, String archived);
public List<YouthMember> getYM(String id, String surname, String first_name, String dob, Blob image, String archived);
}

From this I take it that java.sql.Blob can not be used in GWT. What should I use?

I am storing the images in the database, rather than links to images, as I only have a small number of low resolution images to store so the database should not be over tax by this.

Regards,

Glyn

I have made the following changes:

On the server side in the class MySQLConnection I have added the following method (however it has the listed errors):

public String getImageData(String id){
    ResultSet result = null;
    PreparedStatement ps = null;
    String imageDataString = null;
    try {
        // Read in the image from the database.
        ps = conn.prepareStatement(
              "SELECT at_cub_details.cd_photograph " +
                      "FROM at_cub_details " + 
                      "WHERE at_cub_details.cd_id = \"" + id + "\"");
        result = ps.executeQuery();
        while (result.next()) {
            File file = new File(result.getString(1));
            FileInputStream imageInFile = new FileInputStream(file);
            byte imageData[] = new byte[(int) file.length()];
            imageInFile.read(imageData);

            //Convert Image byte array into Base64 String
            imageDataString = encodeImage(imageData);

            imageInFile.close();
        }

    }
    catch (FileNotFoundException e) {
        System.out.println("getImageData - Image not found" + e);
    } 
    catch (IOException ioe) {
        System.out.println("getImageData - Exception while reading the Image " + ioe);
    }
    catch (SQLException e) {
      //do stuff on fail
        System.out.println("SQLException getImageData 1.");
        e.printStackTrace();
        user = null;
    }
    finally {
        if (result != null) {
            try {
                result.close();
            }
            catch (SQLException e) {
                System.out.println("SQLException getImageData 2.");
                e.printStackTrace();
            }
        }
        if (ps != null) {
            try {
                ps.close();
            }   
            catch (SQLException e) {
                System.out.println("SQLException getImageData 3.");
                e.printStackTrace();
            }
        }
    }
    return imageDataString;
}
 /**
  * Encodes the byte array into base64 string
  * @param imageByteArray - byte array
  * @return String a {@link java.lang.String}
  */
public static String encodeImage(byte[] imageByteArray) {
    return Base64.encodeBase64URLSafeString(imageByteArray); [This line has the error: Multiple markers at this line
- The method encodeBase64URLSafeString(byte[]) is undefined for the 
 type Base64
- Line breakpoint:MySQLConnection [line: 287] - encodeImage(byte[]). However I have import org.apache.commons.codec.binary.Base64;]

}

On the client side I have:

public void renderYouthMemberTable(List<YouthMember> youthMemberList) {
    if (youthMemberList != null) {
        int row = 0;
        int col = 0;
        flexTable.clear();
        for (YouthMember youthMember : youthMemberList) {
            String id = youthMember.getId();

            String imageDataString = getImageData(); [ Error: The method getImageData() is undefined for the type SelectPersonView]

            // Converting a Base64 String into Image byte array
            byte[] imageByteArray = decodeImage(imageDataString);

            // Write a image byte array into file system
            FileOutputStream imageOutFile = new FileOutputStream(
                    "/Users/jeeva/Pictures/wallpapers/water-drop-after-convert.jpg");
            imageOutFile.write(imageByteArray);

            flexTable.setWidget(row, col, new Label(imageByteArray)); [Error: The constructor Label(byte[]) is undefined]
            //flexTable.setWidget(row, col, new Label(youthMember.getId()));
            flexTable.setWidget(row + 1, col, new Label(youthMember.getSurname() + ", " + youthMember.getFirstname()));

            //imageOutFile.close();

            col = col + 1;
            if (col > 7) {
                row = row + 2;
                col = 0;
            }
        }
    }

}

/**
 * Decodes the base64 string into byte array
 * @param imageDataString - a {@link java.lang.String}
 * @return byte array
 */
public static byte[] decodeImage(String imageDataString) {
    return Base64.decodeBase64(imageDataString); [ With the error: The method decodeBase64(byte[]) in the type Base64 is not applicable for the arguments (String)]
    }

I copied this code from: http://www.myjeeva.com/2012/07/how-to-convert-image-to-string-and-string-to-image-in-java/

Regards,

Glyn

Glyn
  • 1,933
  • 5
  • 37
  • 60
  • What are you going to do with the Blob (or BlobReplacement) once it hits the client? How are you going to actually draw that image? Have you thought about just returning a String representing the URL to that image, and having a servlet that just serves up those images? – Colin Alworth Feb 04 '13 at 22:37
  • I am going to display the image in a flextable. Am I being overly simplistic in assuming that I can store an image in a table and then display that image in the same way that I store and display a string or integer? I would prefer to keep all my data in the one database. Regards, Glyn. – Glyn Feb 04 '13 at 23:33
  • Possibly - have you done HTML work before? Strings and integers can both easily be rendered as the same thing - strings. Images cannot be drawn by just using strings (unless you are just talking about `` tags), though you can get close with data: urls if you are willing to give up older versions of IE. – Colin Alworth Feb 05 '13 at 00:23
  • Hi Colin, I understand that I can display an image in html by using the tag src. However, I understand that the source must be a file and optionally a directory path (e.g., images\picture.jpg). How do I, in Eclipse java GWT, extract an image (i.e., a small jpg picture - head and shoulders) from a MySQL table where it is stored as a longblob and then display the image in a widget (i.e., flextable). The next step is to make the image selectable so the user is given a selection of images and on selecting one they are taken to the person's details view. Regards, Glyn. – Glyn Feb 05 '13 at 01:01
  • You are adding a lot of pieces to the puzzle here - Eclipse can be used to _write_ the code, but it won't run it; GWT client code only runs in the browser, so it cannot extract files to the filesystem on the server. You must have a servlet which serves up this file. If it were me, I wouldn't bother extracting it to the filesystem, but instead just stream out the results from another servlet specially built for this task. As far as selecting images - walk first, then run - otherwise this question is just going to grow and grow. – Colin Alworth Feb 05 '13 at 01:31
  • Sorry I should not have mentioned the second part. The problem I have is that I can not get past the DBConnection.java error. In this I define my method getYM (which is in a Servlet MySQLConnection.java) as "public List getYM(String id, String surname, String first_name, String dob, Blob image, String archived);". However, the "Blob image" causes an error. GWT does not seem to recognise "import java.sql.Blob". getYM reads the DB and passes the result back to SelectPersonView.java to display the results. Why can I not use "Blob image" in DBConnection and what should I use instead? – Glyn Feb 05 '13 at 02:07
  • Right - the short answer is Blob can't be passed to the client. The server can talk to the database using Blob, but you can't pass Blob to the client. Solving the answer of 'how can an image be drawn' will lead to not needing Blob - since the client can't render images with Blob anyway. It sort of a chicken/egg problem - you have two problems, caused by each other ;-). – Colin Alworth Feb 05 '13 at 03:26
  • I have tried replacing Blob with String and then on the client side converting the string to a byte array Byte[]. However, I get the error message "Can not cast from String to Byte[]". Any ideas? Regards, Glyn. – Glyn Feb 05 '13 at 04:39

1 Answers1

0

When you use GWT, don't forget that your final code is javascript. So some classes are not availables.

But:

-> Images in GWT can have a servlet url for source url (with parameters).

-> other way described here: GWT - image from database : use a service rpc that return base64 string + image initialization on callback.

hope is usefull for your problem.

Community
  • 1
  • 1
Catux
  • 21
  • 2
  • Hi fmy, thank you for this information. I have been looking at something similar. However, I first need to resolve the first error. In DBConnection I define "public List getYM(String id, String surname, String first_name, String dob, Blob image, String archived);". This produces the error. So what do I do? Do I change "Blob" to "String" through all my code? However, this does not match the MySQL column definition; does this matter? Or should I change my table, convert the image and store the image as a String? – Glyn Feb 05 '13 at 22:13
  • I have tried changing all "Blob" to "String". When I try to implement the recomended solution for the line "String base64 = Base64Utils.toBase64(result.getString(5));" I get the error " Line breakpoint:MySQLConnection [line: 182] - getYM(String, String, String, String, String, String) - The method toBase64(byte[]) in the type Base64Utils is not applicable for the arguments (String)". – Glyn Feb 05 '13 at 22:20
  • So before I do anything I need to know how I should store the image and recover the image (i.e., the correct definition in DBConnection.java "public List getYM(String id, String surname, String first_name, String dob, String image, String archived);". Thanks for your help. Regards, Glyn. – Glyn Feb 05 '13 at 22:20
  • I think your first problem is use a rpc service named DBConnection. I think your remote service should be a wrapper between db datas and GUI representation (and should be -features oriented-). The conversion depends on your blob content (already base64 ?). It's not really a GWT problem, just problem to retrieve datas you have stored and convert them: but when you now the input format (blob content) and the output format (base64 string), your problem became less specific and you can find solution outside GWT topics :-). hope i have understood well your problem. regards – Catux Feb 06 '13 at 16:24
  • Hi fmy, I know you are trying your best to help; and I sincerely thank you for that. However, I am afraid I do not have the java experience to understand your reply. I have found some other information online and I will update my post with my attempt from this. Regards, Glyn. – Glyn Feb 09 '13 at 23:24