Getting Error java.lang.NoClassDefFoundError: sun/

2019-08-23 07:50发布

问题:

I am writing a rest client using java.net which should do a PATCH request. But as PATCH is not a supported method in java.net, I used reflection to make it supported by changing the code like

private void updateConnectionToSupportPatchRequest(final HttpURLConnection conn)
    throws ReflectiveOperationException {
    try {
        final Object targetConn;
        if (conn instanceof HttpsURLConnectionImpl) {
            final Field delegateField = HttpsURLConnectionImpl.class.getDeclaredField("delegate");
            delegateField.setAccessible(true);
            targetConn = delegateField.get(conn);
        } else {
            targetConn = conn;
        }
        final Field methodField = HttpURLConnection.class.getDeclaredField("method");
        methodField.setAccessible(true);
        methodField.set(targetConn, "PATCH");
    } catch (final NoSuchFieldException ex) {
        LOGGER.error("NoSuchFieldException: {} ", ex.getMessage());
    }
}

but when I deploy my application which uses my rest client in JBoss, I get this error -

java.lang.NoClassDefFoundError: sun/net/www/protocol/https/HttpsURLConnectionImpl

I looked up on this error and came across this post http://planet.jboss.org/post/dealing_with_sun_jdk_related_noclassdeffounderror_under_jboss

I tried the suggested solution in the post still getting the same error. Any ideas on how to get passed this issue?

P.S. I cannot use the Apache HttpClient or RestEasy(Jboss) as there is another 3PP being used in the project which does not support Apache HttpClient

回答1:

Have you tried using the workaround X-HTTP-Method-Override before trying to fiddle with internal classes of the JDK? If that's the case, you can use the instance's getClass-method to access fields and use isAssignableFrom as alternative to instanceof.

Another approach to get rid off specifying concrete classes is just trying to get the field in HttpsURLConnection and assuming a non-Https-URLConnection if the field can't be found. This might look like the following code:

private void updateConnectionToSupportPatchRequest(final HttpURLConnection conn) 
    throws ReflectiveOperationException {
    try {
        final Object targetConn = conn;
        try {
            final Field delegateField = findField(conn.getClass(), "delegate");
            delegateField.setAccessible(true);
            targetConn = delegateField.get(conn);
        }
        catch(NoSuchFieldException nsfe) {
            // no HttpsURLConnection
        }
        final Field methodField = findField(conn.getClass(), "method");
        methodField.setAccessible(true);
        methodField.set(targetConn, "PATCH");
    } catch (final NoSuchFieldException ex) {
        LOGGER.error("NoSuchFieldException: {} ", ex.getMessage());
    }
}

private Field findField(Class clazz, String name) throws NoSuchFieldException {
    while (clazz != null) {
        try {
            return clazz.getDeclaredField(name);
        }
        catch(NoSuchFieldException nsfe) {
            // ignore
        }
        clazz = clazz.getSuperclass();
    }
    throw new NoSuchFieldException(name);
}

But this might fail at another level because - obviously - the class that is used within JBoss is not the one you implemented the workaround, so fields and methods might be named differently.