0

I could say I'm new to this whole programming world!

The case is that I'm doing a project with JHipster integrated with Android, using Retrofit2.

Well, what I'm trying to do is save an image to the database (MySQL), which is saved on a byte[] field.

That's what I have on the User entity in backend:

@Entity
@Table(name = "usuario")
public class Usuario implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @NotNull
    @Column(name = "name", nullable = false)
    private String name;

    @Lob
    @Column(name = "image")
    private byte[] image;

    @Column(name = "image_content_type")    
    private String imageContentType;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public byte[] getImage() {
        return image;
    }

    public void setImage(byte[] image) {
        this.image = image;
    }

    public String getImageContentType() {
        return imageContentType;
    }

    public void setImageContentType(String imageContentType) {
        this.imageContentType = imageContentType;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Usuario usuario = (Usuario) o;
        if(usuario.id == null || id == null) {
            return false;
        }
        return Objects.equals(id, usuario.id);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(id);
    }

    @Override
    public String toString() {
        return "Usuario{" +
            "id=" + id +
            ", name='" + name + "'" +
            ", image='" + image + "'" +
            ", imageContentType='" + imageContentType + "'" +
            '}';
    }
}

And this is what I have on Android Class:

public class Usuario {
    Long id;
    String name;
    String image;
    String imageContentType;

    public Usuario() {
    }

    public Usuario(Long id, String name, String image) {
        this.id = id;
        this.name = name;
        this.image = image;

    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getImage() {
        return image;
    }

    public void setImage(String image) {
        this.image = image;
    }

    public String getImageContentType() {
        return imageContentType;
    }

    public void setImageContentType(String imageContentType) {
        this.imageContentType = imageContentType;
    }

I tried to save the image on a Byte[] in Android too, but since I can't get the response when I'm trying to get the user's information (seems to be a problem with the JSON file that I receive from backend, I receive an Array when Android wants an String), I have to use an String. So I've implemented a method on the REST resource to convert that String to Byte[], which looks like the following:

@RequestMapping(value = "/usuarios/{img}/{id}",
    method = RequestMethod.PUT,
    produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
public ResponseEntity<Usuario> convertImage(@Valid @RequestBody Usuario usuario, @RequestBody String img, @RequestBody Long id) {
    log.debug("REST request to get Usuario : {}", id, img);
    usuario = usuarioRepository.findOne(id);
    byte[] b = img.getBytes();
    usuario.setImage(b);
    Usuario result = usuarioRepository.save(usuario);
    return ResponseEntity.ok()
        .headers(HeaderUtil.createEntityUpdateAlert("usuario", usuario.getId().toString()))
        .body(result);
}

I guess I'm not correctly using the @RequestMapping, but somehow from JHipster CRUD using the API that method works fine, the problems seems to be on the Android/Retrofit2 methods, which look like this:

That's the service:

@Multipart
@PUT("/api/usuarios/{id}/{img}")
Call<Usuario> convertImage(
        @Header("Authorization") String Authorization,
        @Part("img") String img, @Part("id") Long id
);

What I have on the UserManager:

public synchronized void convertImage(final UsuarioCallback usuarioCallback, String img, Long id) {
    Call <Usuario> call = usuarioService.convertImage(UserLoginManager.getInstance(context).getBearerToken(), img, id);
    call.enqueue(new Callback<Usuario>() {
        @Override
        public void onResponse(Call<Usuario> call, Response<Usuario> response) {

            int code = response.code();

            if (code == 200 || code == 201) {

            } else {
                usuarioCallback.onFailure(new Throwable("ERROR" + code + ", " + response.raw().message()));
            }
        }

And this is how I'm calling and transfering the information:

ByteArrayOutputStream stream = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.PNG, 90, stream); 
    byte[] byte_arr = stream.toByteArray();
    String imgString = Base64.encodeToString(byte_arr,
            Base64.DEFAULT);
    Usuario usuario = new Usuario();
    usuario.setId(Long.parseLong("1"));
    Long id = usuario.getId();
    UsuarioManager.getInstance(view.getContext()).convertImage(EditProfile.this, imgString, id);

With all this I'm getting the error I show in the title, so I don't really know what can be wrong with this.

I guess that's all the information I should provide, I'm sorry if I'm missing something but I'm kinda lost with this error and I've been stucked here for weeks.

Thanks you beforehand!

Angie
  • 1
  • 1

1 Answers1

0

I would suggest taking a different approach and not putting the image in the DB or the JSON.

Database: Designed to save, search, sort many small pieces of data, it is typically better to put a reference (perhaps UUID) to a binary file on your filesystem. Here is a good writeup on the considerations

JSON It is formatted text. Encoding byte[] data in text which is then encoded as a byte[] to send across the network will add a lot of overhead. While it is possible most people (and most JSON libs) are more suited to sharing a URL to the image or making a REST endpoint directly for the images.

Community
  • 1
  • 1
cyroxis
  • 3,661
  • 22
  • 37