-4

I was going through reflection API, but was not able to relate creating object using reflection in real time scenario/use case in real time application. Have anyone used reflection to create objecct using reflection and in which use case?

amitguptageek
  • 537
  • 3
  • 13

1 Answers1

2

Here are a couple of use cases:

1) If you want flexibility of implementation and don't want to use dependency injection frameworks you might use a system property defined on start up of the application to specify the implementation class to use. JAXP uses many system properties such as javax.xml.parsers.DocumentBuilderFactory for this.

For example if you had an interface/abstract class called AutoRideService and wanted to be able to configure the implementation used at runtime you could get it like this:

private static AutoRideService lookupAutoRideService() {
    String className = System.getProperty("autorideservice.classname");
    try {
        @SuppressWarnings("unchecked")
        Class<AutoRideService> clazz = (Class<AutoRideService>) Class.forName(className);
        return clazz.newInstance();
    } catch (Exception ex) {
        throw new IllegalStateException("Failed to lookup auto ride service using class name: " + className, ex);
    }
} 

2) If you need to work with different and incompatible versions of classes in the same program. Here you can use multiple class loaders and reflection.

For example I had some Oauth tokens stored in a db where they were created by an old version of Spring Security Oauth2. I wanted to upgrade the version of Spring Security Oauth2 and the stored tokens but the new version had significant and backward incompatible changes to classes needed to deserialize the tokens. Here is a snippet of code for this:

/**
 * This takes serialization data of the old authentication object and then
 * reads it as an object using a separate class loader which has the old version of the spring and spring security classes
 * We then use reflection to access the compatible fields and then use this data to construct the new class version object
 * @param oldAuthData The serialized data created with the old version of the classes
 * @return The deserialized OAuth2Authentication object constructed with the new class versions
 * @throws IOException
 * @throws ClassNotFoundException
 * @throws NoSuchMethodException
 * @throws IllegalAccessException
 * @throws InvocationTargetException
 */
private OAuth2Authentication deserializeOAuth2Authentication(byte[] oldAuthData) throws IOException, ClassNotFoundException, NoSuchMethodException,
        IllegalAccessException, InvocationTargetException {
    OAuth2Authentication auth = null;
    ObjectInputStream ois = new CustomObjectInputStream(new ByteArrayInputStream(oldAuthData), this.deserialisationClassLoader);
    try {
        Object obj = ois.readObject();

        // the instance of this is the old OAuth2Authentication however we cannot cast
        // so have to use reflection to access the fields and data
        // and then construct a new OAuth2Authentication from this

        Object oldAuthorizationRequest = MethodUtils.invokeMethod(obj, "getAuthorizationRequest", NO_ARGS);

        Object authentication = MethodUtils.invokeMethod(obj, "getUserAuthentication", NO_ARGS);
        Object principal = MethodUtils.invokeMethod(authentication, "getPrincipal", NO_ARGS);
        Object credentials = MethodUtils.invokeMethod(authentication, "getCredentials", NO_ARGS);
        Collection<GrantedAuthority> authorities = convertAuthorities((Collection<?>) MethodUtils.invokeMethod(authentication, "getAuthorities", NO_ARGS));

        // now construct the oauth authentication object with the new auth and request
        Authentication authToken = new UsernamePasswordAuthenticationToken(principal, credentials, authorities);
        AuthorizationRequest authReq = convertAuthorizationRequest(oldAuthorizationRequest);
        auth = new OAuth2Authentication(authReq, authToken);

    } finally {
        ois.close();
    }
    return auth;
}
Conor Roche
  • 201
  • 1
  • 3