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

ActiveJDBC: Review the architecture for converters #1242

Open
ipolevoy opened this issue Oct 13, 2022 · 6 comments
Open

ActiveJDBC: Review the architecture for converters #1242

ipolevoy opened this issue Oct 13, 2022 · 6 comments

Comments

@ipolevoy
Copy link
Member

ipolevoy commented Oct 13, 2022

It seems to have a few flaws:

  1. The model.set(attr, val) method calls a model.get(attr), which is not semantically correct
  2. The converters are called inside the get(attr) as well as inside the set(attr)
  3. This is not working, but we'd expect this world: model.set("created_at", "10/11/2022");
  4. The Converted API is obtuse with too much to implement by a framework user. Needs to be simplified.
@ipolevoy
Copy link
Member Author

related issue: #1241

@Dieken
Copy link

Dieken commented Oct 24, 2022

I just did some dirty hack to make ActiveJDBC can accept an encrypted object for query parameters and return encrypted object too from result set.

public class NameEnc {
    private String encrypted;
   ...
   public void setEncrypted(String s) { ... }
   public String getEncrypted() { ... }

    public static class ActiveConverter implements org.javalite.conversion.Converter<Object, Object> {

        public static final ActiveConverter INSTANCE = new ActiveConverter();

        @Override
        public boolean canConvert(Class src, Class dst) {
            return true;
        }

        @Override
        public Object convert(Object src) {
            if (src == null) {
                return null;
            }

            if (src instanceof NameEnc) {
                return ((NameEnc) src).getEncrypted();
            } else if (src instanceof String) {
                // XXX: ActiveJDBC actually always requires String for VARCHAR column,
                // XXX: set() and get() from user code have elements[3] not in ActiveJDBC code,
                // XXX: so it returns Encrypted only for user code.
                StackTraceElement[] elements = Thread.currentThread().getStackTrace();
                boolean internalCall = elements[3].getClassName().startsWith("org.javalite.activejdbc.");
                if (internalCall) {
                    return src;
                } else {
                    NameEnc e = new NameEnc();
                    e.setEncrypted((String) src);
                    return e;
                }
            } else {
                throw new UnsupportedOperationException("can't convert from class " + src.getClass());
            }
        }
    }
}

My entity class:

@Table("TEST.account")
public class AccountModel extends Model {

    static {
        convertWith(NameEnc.ActiveConverter.INSTANCE, "name_enc");
        ...
    }
}

@Dieken
Copy link

Dieken commented Oct 24, 2022

Possible converter interface:

public interface Converter<T> {
      // cls is required so that we can share an converter among sub classes of T
      T fromDatabase(ResultSet rs, int i, Class<T> cls);

      void toDatabase(PreparedStatement ps, int i, T t);
}

The objects in get(), set() should be just Java object, they are mapped to JDBC type only when call into JDBC.

@ipolevoy
Copy link
Member Author

@Dieken, thanks for the idea, but I have a much simpler implementation for what you are doing here. I will publish a blog article on the topic sometime this week, and share it with you.

@Dieken
Copy link

Dieken commented Dec 28, 2022

Two month passed, just a ping … ;-)

@ipolevoy
Copy link
Member Author

@Dieken, sorry for the late response. I will get this published in the next 3 days,

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

No branches or pull requests

2 participants