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 ?
Added spring class AbstractJdbcCall.java in the project folder with exact package name. Then added the below method to return the callMetaDataContext
Now CustomJDBCCall look like this
This solved my issue