Search code examples
javaspring-bootspring-jdbcjava-21

Caused by: java.lang.NoSuchFieldException: modifiers


I am working on an existing old spring-boot code while migrating/upgrading to spring-boot 2.7.16 and jdk version upgraded from 8 to 21 I am getting this error

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.List;
import org.apache.log4j.Logger;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.core.simple.AbstractJdbcCall;
import org.springframework.jdbc.core.simple.SimpleJdbcCall;
public class CustomJDBCCall extends SimpleJdbcCall {
private final CustomCallMetaDataContext callMetaDataContext;
private static final String CALL_META_DATA_CONTEXT = "callMetaDataContext";
private static final String MODIFIERS = "modifiers";
private static final Logger LOGGER =Logger.getLogger(CustomJDBCCall.class);

public CustomJDBCCall(JdbcTemplate jdbcTemplate) throws Exception {
    super(jdbcTemplate);
    try {
        callMetaDataContext = new CustomCallMetaDataContext();
        
        // Access private field
        Field callMetaDataContextField = 
        AbstractJdbcCall.class.getDeclaredField(CALL_META_DATA_CONTEXT);
        callMetaDataContextField.setAccessible(true);

   
        Field modifiersField = Field.class.getDeclaredField(MODIFIERS);
        modifiersField.setAccessible(true);
        modifiersField.setInt(callMetaDataContextField, 
     callMetaDataContextField.getModifiers() & ~Modifier.FINAL);


        callMetaDataContextField.set(this, this.callMetaDataContext);
      } catch (NoSuchFieldException | IllegalAccessException ex) {
        LOGGER.error("Error while using custom JDBC", ex);
        throw new RuntimeException("Exception thrown overriding 
     AbstractJdbcCall.callMetaDataContext field", ex);
     } catch (Exception ex) {
        LOGGER.error("Error while using custom JDBC", ex);
        throw ex;
     }
   }

    public List<SqlParameter> getParamerters() throws Exception {
    return this.callMetaDataContext.getCallParameters();
    }
 }

In this code the exception is thrown in the line

 Field modifiersField = Field.class.getDeclaredField(MODIFIERS);

Caused by: java.lang.NoSuchFieldException: modifiers at java.base/java.lang.Class.getDeclaredField(Class.java:2782)

Before it was working fine in jdk 8. This is existing code not written by me and I think here accessing the private final field and setting the value. Am I correct ? I think in the Jdk version 12 and above modifying the final and private variable is not possible or disabled is there any work around ?


Solution

  • Added spring class AbstractJdbcCall.java in the project folder with exact package name. Then added the below method to return the callMetaDataContext

    public CallMetaDataContext getCallMetaDataContext() {
        return this.callMetaDataContext;
    }
    

    Now CustomJDBCCall look like this

     public class CustomJDBCCall extends SimpleJdbcCall {
            
     public CustomJDBCCall(JdbcTemplate jdbcTemplate) throws Exception 
      {
          super(jdbcTemplate);  
       
      }
    
      public List<SqlParameter> getParamerters() throws Exception {
        return this.getCallMetaDataContext().getCallParameters();
      }
     }
    

    This solved my issue