3

Before I wander off and re-create the wheel, does anyone know of a JPA wrapper that turns the unchecked exceptions JPA throws into checked exceptions?

Not looking for an argument about why I should not want checked exceptions, I do want them :-)

4
  • Still, why would you want to do that? If there is no such wrapper, maybe there is a reason behind it? :-P Commented Nov 17, 2010 at 19:05
  • 'cuase most people are not as picky as I am about exceptions? :-) Commented Nov 17, 2010 at 19:43
  • Did you end up rolling your own? Care to share? Commented Apr 1, 2011 at 8:54
  • I started on it and then realized doing so would have issues. I'll take another look and put an answer up in the next few days... perhaps someone smarter than me can figure it out :-) Commented Apr 1, 2011 at 14:38

1 Answer 1

1

You can do 99% of rolling your own using the code below. It will leave you with two compile errors due to the members of a Collection needing to be encapsulated, but it does take you past the point where it is no longer worth automating.

package so;

import javax.persistence.*;

import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.*;

public class CheckedPersistenceMaker {
static final String PACKAGE = "stackoverflow.javax.persistence";

static final String PACKAGE_DIR = PACKAGE.replace('.', '/');

static Class<?>[] CLASSES = new Class<?>[] { Cache.class,
        EntityManager.class, EntityManagerFactory.class,
        EntityTransaction.class, Parameter.class,
        PersistenceUnitUtil.class, PersistenceUtil.class,
        Persistence.class, Query.class, Tuple.class, TupleElement.class,
        TypedQuery.class };


private static String getName(Class<?> c) {
    String name = c.getName();
    for(Class<?> p:CLASSES) {
        if (p.equals(c))
            return PACKAGE + ".Checked"
                    + name.substring(name.lastIndexOf('.') + 1);
    }
    return c.getName();
}


static void generateWrapper(Class<?> c) throws Exception {
    String name = c.getName();
    TypeVariable<?>[] genType = c.getTypeParameters();
    String varNames = "";
    if (genType != null && genType.length != 0) {
        StringBuilder b = new StringBuilder();
        b.append("<");
        for(int i = 0;i < genType.length;i++) {
            if (i > 0) b.append(",");
            b.append(genType[i].getName());
        }
        b.append(">");
        varNames = b.toString();
    }
    name = "Checked" + name.substring(name.lastIndexOf('.') + 1);
    File javaFile = new File(PACKAGE_DIR + "/" + name + ".java");
    javaFile.getParentFile().mkdirs();
    FileWriter w = new FileWriter(javaFile);
    w.write("package " + PACKAGE + ";\n");
    w.write("public class " + name + varNames + " {\n");
    w.write("    private final " + c.getName() + varNames
            + " wrapped;\n\n    ");
    w.write(name + "(" + c.getName() + varNames
            + " original) {\nwrapped=original;\n}\n\n");
    w.write("    public " + c.getName() + varNames
            + " getOriginal() { return wrapped; }\n\n");
    Method[] ms = c.getDeclaredMethods();
    for(Method m:ms) {
        if (!Modifier.isPublic(m.getModifiers())) continue;
        w.write("    ");
        String s = m.toGenericString();
        s = s.replace(" abstract ", " ");
        s = s.replace(c.getName() + ".", "");

        String q = s.substring(0, s.indexOf('('));
        if (q.indexOf('<',10) != -1) q = q.substring(0, q.indexOf('<',10));
        boolean needsTranslate = false;

        for(Class<?> cc:CLASSES) {
            String ccn = cc.getName();
            if (q.indexOf(ccn) != -1) needsTranslate = true;
            String ccc = ccn.replace(cc.getPackage().getName() + ".",
                    PACKAGE + ".Checked");
            s = s.replace(ccn, ccc);
        }

        int pc = 0;
        int p = s.indexOf('(');
        if (s.charAt(p + 1) != ')') {
            StringBuilder b = new StringBuilder(s);
            int g = 0;
            char ch;
            do {
                ch = b.charAt(p);
                switch (ch) {
                case '<': {
                    g++;
                    break;
                }
                case '>': {
                    g--;
                    break;
                }
                case ',':
                case ')': {
                    if (g == 0) {
                        String pa = " p" + pc;
                        b.insert(p, pa);
                        pc++;
                        p += pa.length();
                    }
                    break;
                }
                }
                p++;
            } while( ch != ')' );
            s = b.toString();
        }

        w.write(s);

        w.write(" throws CheckedPersistenceException");

        Class<?>[] excs = m.getExceptionTypes();
        for(Class<?> e:excs) {
            w.write(", " + e.getName());
        }
        w.write(" {\n        try {\n            ");

        Class<?> ret = m.getReturnType();
        if (!ret.equals(Void.TYPE)) {
            w.write("return ");
            if (needsTranslate) {
                String retName = ret.getName();
                retName = retName.replace(c.getPackage().getName() + ".",
                        PACKAGE + ".Checked");
                w.write("new " + retName + "(");
            }
        }

        if (Modifier.isStatic(m.getModifiers())) {
            w.write(c.getName() + "." + m.getName() + "(");
        } else {
            w.write("wrapped." + m.getName() + "(");
        }

        Class<?> paramTypes[] = m.getParameterTypes();
        for(int i = 0;i < pc;i++) {
            if (i > 0) w.write(',');

            boolean isChecked = false;
            for(int j=0;j<CLASSES.length;j++) {
                if( CLASSES[j].equals(paramTypes[i]) ) isChecked=true;
            }
            w.write("p" + i);
            if(isChecked) w.write(".getOriginal()");
        }
        w.write(')');

        if (needsTranslate) w.write(')');
        w.write(";\n        } catch ( javax.persistence.PersistenceException e ) { throw new CheckedPersistenceException(e); }\n    }\n\n");
    }
    w.write("}\n");
    w.close();
}


public static void main(String[] args) throws Exception {
    for(Class<?> c:CLASSES) {
        generateWrapper(c);
    }
}
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.