Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Abstract Method NullSafeSet SessionImplementor S3Blob Issue #4

Open
cmazzochi81 opened this issue Nov 9, 2017 · 12 comments
Open

Abstract Method NullSafeSet SessionImplementor S3Blob Issue #4

cmazzochi81 opened this issue Nov 9, 2017 · 12 comments

Comments

@cmazzochi81
Copy link

cmazzochi81 commented Nov 9, 2017

This error is occurring when my application is attempting to save information about a photo into a database. Just before it does that it sends the photo to Amazon S3. And that is a successful operation. But when it tries to save the information about the photo into my database, the app crashes.

Can anybody see what I need to do in order to get through this error? I'd appreciate it. Thanks, CM

Here's the stack trace:
hibernateerror

It boils down to these two methods:

@Override
public Object nullSafeGet(ResultSet rs, String[] names, Object o, 
SessionImplementor session) throws HibernateException, SQLException {
    String val = StringType.INSTANCE.nullSafeGet(rs, names[0]);
    if (val == null || val.length() == 0 || !val.contains("|")) {
        return new S3Blob();
    }
    return new S3Blob(val.split("[|]")[0], val.split("[|]")[1]);
}

@Override
public void nullSafeSet(PreparedStatement ps, Object o, int i, 
SessionImplementor session) throws HibernateException, SQLException {
    if (o != null) {
        ps.setString(i, ((S3Blob) o).bucket + "|" + ((S3Blob) o).key);
    } else {
       ps.setNull(i, Types.VARCHAR);
    }
}

Here's that entire class:

play.modules.s3blobs.S3Blob

import java.sql.SQLException;
import java.sql.Types;

import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.type.StringType;
import org.hibernate.usertype.UserType;

import play.db.Model.BinaryField;
import play.libs.Codec;

import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.S3Object;

public class S3Blob implements BinaryField, UserType {

static String s3Bucket;
static AmazonS3 s3Client;
private String bucket;
private String key;

public S3Blob() {
}

private S3Blob(String bucket, String s3Key) {
    this.bucket = bucket;
    this.key = s3Key;
}

@Override
public InputStream get() {
    S3Object s3Object = s3Client.getObject(bucket, key);
    return s3Object.getObjectContent();
}

@Override
public void set(InputStream is, String type) {
    this.bucket = s3Bucket;
    this.key = Codec.UUID();
    ObjectMetadata om = new ObjectMetadata();
    om.setContentType(type);
    s3Client.putObject(bucket, key, is, om);
}

@Override
public long length() {
    ObjectMetadata om = s3Client.getObjectMetadata(bucket, key);
    return om.getContentLength();
}

@Override
public String type() {
    ObjectMetadata om = s3Client.getObjectMetadata(bucket, key);
    return om.getContentType();
}

@Override
public boolean exists() {
    ObjectMetadata om = s3Client.getObjectMetadata(bucket, key);
    return om != null;
}

@Override
public int[] sqlTypes() {
    return new int[] { Types.VARCHAR };
}

@Override
public Class returnedClass() {
    return S3Blob.class;
}

@Override
public boolean equals(Object o, Object o1) throws HibernateException {
    return o == null ? false : o.equals(o1);
}

@Override
public int hashCode(Object o) throws HibernateException {
    return o.hashCode();
}

@Override
public Object nullSafeGet(ResultSet rs, String[] names, Object o, SessionImplementor session) throws 
HibernateException, SQLException {
    String val = StringType.INSTANCE.nullSafeGet(rs, names[0]);
    if (val == null || val.length() == 0 || !val.contains("|")) {
        return new S3Blob();
    }
    return new S3Blob(val.split("[|]")[0], val.split("[|]")[1]);
}

@Override
public void nullSafeSet(PreparedStatement ps, Object o, int i, SessionImplementor session) throws 
HibernateException, SQLException {
    if (o != null) {
        ps.setString(i, ((S3Blob) o).bucket + "|" + ((S3Blob) o).key);
    } else {
        ps.setNull(i, Types.VARCHAR);
    }
}

@Override
public Object deepCopy(Object o) throws HibernateException {
    if (o == null) {
        return null;
    }
    return new S3Blob(this.bucket, this.key);
}

@Override
public boolean isMutable() {
    return true;
}

@Override
public Serializable disassemble(Object o) throws HibernateException {
    throw new UnsupportedOperationException("Not supported yet.");
}

@Override
public Object assemble(Serializable srlzbl, Object o) throws HibernateException {
    throw new UnsupportedOperationException("Not supported yet.");
}

@Override
public Object replace(Object o, Object o1, Object o2) throws HibernateException {
    throw new UnsupportedOperationException("Not supported yet.");
}
}

Application.java around line 56

public static void doCreateItem(
    @Valid String title, 
    @Valid Integer days, 
    @Valid Float startBid, 
    @Valid Float buyNowPrice,
    @Valid Float deliveryCost,
    @Valid Boolean buyNowEnabled,
    @Valid String description, 
@Valid File photo) throws FileNotFoundException

{

if (validation.hasErrors()){
params.flash();
validation.keep();
createAuctionItem();    
}
final AuctionItem item = new AuctionItem();
item.photo = new S3Blob();
item.photo.set(new FileInputStream(photo), 
    MimeTypes.getContentType(photo.getName()));
item.createdBy = Authenticate.getLoggedInUser();
(Line56) item.save();
show(item.id);
}
@jamesward
Copy link
Owner

This is because by default the Heroku buildpack uses Play 1.2 and it looks like this module isn't compatible with Play 1.2. I've tested it with Play 1.4 and JDK 8. To tell heroku to use those versions update your conf/dependencies.yml to include:

require:
    - play 1.4.5

And create a system.properties with:

java.runtime.version=1.8

When you push to Heroku you should see the build pulling in JDK 1.8 and Play 1.4.5.

@cmazzochi81
Copy link
Author

cmazzochi81 commented Nov 13, 2017 via email

@jamesward
Copy link
Owner

Sorry for not being more clear, the system.properties file has to be in the root. Can you try that with 1.4.5 and see how it goes?

@jamesward
Copy link
Owner

BTW, I've updated this project to work on Heroku with Play 1.4.5 and JDK 8 so you can reference this repo for layout and config.

@cmazzochi81
Copy link
Author

cmazzochi81 commented Nov 13, 2017 via email

@cmazzochi81
Copy link
Author

cmazzochi81 commented Nov 13, 2017 via email

@jamesward
Copy link
Owner

This repo is a sample app for the s3blobs module. I've tested that this repo works as expected on Heroku.

@cmazzochi81
Copy link
Author

cmazzochi81 commented Nov 13, 2017 via email

@cmazzochi81
Copy link
Author

cmazzochi81 commented Nov 13, 2017 via email

@jamesward
Copy link
Owner

Ah, well at least we now know what versions are being used on Heroku. :)

There was a Pull Request a while back on the s3blobs project that might be related to this:
jamesward/S3-Blobs-module-for-Play#9

Think that might be related? If so, I can make that change (it was never merged) and release a new version.

@jamesward jamesward reopened this Nov 13, 2017
@cmazzochi81
Copy link
Author

cmazzochi81 commented Nov 13, 2017 via email

@jamesward
Copy link
Owner

I really have no idea what the problem is so I'm totally taking random shots in the dark. :)

Next step is to make sure you are using the s3blobs Play module like in https://github.com/jamesward/plays3upload/blob/master/conf/dependencies.yml

You don't need the localModule stuff as that is for development of the module.

Also, I'm curious what the value of MimeTypes.getContentType(photo.getName()) is because maybe it's null and things are happy due to that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants