Mockito: How to make the service call throw exception - java

I have Hystrix commands in my class which I need to test. I am able to mock all the code except the fallback. To execute the fallback, I need to make my hystrix wrapped method to throw a timeout exception. I don't get how to do that. Can someone help me with it? I tried opening the circuit with #Enablecircuitbreaker on the test class, but that didn't invoke any Hystrix exception :(
#Mock
private MDMConnectorService service;
#InjectMocks
private AIAUtilities aiaUtilities;
#Test
public void testFetchCustomerAccountDetailsHystrixTimeoutException() throws Exception {
try {
ConfigurationManager.getConfigInstance()
.setProperty("hystrix.command.AIAClientCommand.circuitBreaker.forceOpen", "true");
Mockito.when(service.fetchCustomerAccount(any(GetCustomerAccountType.class))).thenReturn(getTestAIARecord());
GetCustomerAccountResponseType responseType = aiaUtilities
.fetchCustomerAccountDetails(accountNumber);
Assert.assertFalse(true);// if the flow came here, the test case has failed
} catch (Exception ex) {
if (ex instanceof DataAccessException) {
assertEquals(Constants.ERRCODE_AIA_QUERY_TIMED_OUT,
((DataAccessException) ex).getErrorCode());
} else {
throw ex;
}
}
finally {
ConfigurationManager.getConfigInstance()
.setProperty("hystrix.command.AIAClientCommand.circuitBreaker.forceOpen", "false");
}
}
In this test, the command wrapped by hystrix is being called at
GetCustomerAccountResponseType responseType = aiaUtilities
.fetchCustomerAccountDetails(accountNumber);
The code of AIAUtilities having the hystrix command and corresponding fallback is
#HystrixCommand(commandKey = "AIAClientCommand", fallbackMethod = "aiaClientCommandFallback")
public GetCustomerAccountResponseType fetchCustomerAccountDetails(String accountNumber)
throws DataAccessException {
GetCustomerAccountResponseType response;
try {
if (generalUtil.isObjectEmpty(authHeader)) {
authHeader = iamUtilities.createAuthHeaderAndRenewOfflineTicket();
}
factory = getFactory();
request = getRequest();
accountNumberType = getAccountNumberType();
accountNumberType.setValue(accountNumber);
request.setCustomerAccountNumber(accountNumberType);
request.setSourceId(Constants.VAL_QUICKBASE_SOURCE_AIA);
serviceClass = getServiceClass();
service = getService();
provider = getProvider();;
provider.getRequestContext().put("Authorization", authHeader);
provider.getRequestContext().replace("SOAPAction", "fetchCustomerAccount");
provider.getRequestContext().put("Content-Type", "text/xml");
response = service.fetchCustomerAccount(request);
} catch (DataAccessException e) {
throw e;
}
catch (Exception e) {
if(e instanceof HystrixRuntimeException && e.getCause() instanceof TimeoutException) {
DataAccessException dataAccessException = (DataAccessException) ((HystrixRuntimeException) e)
.getFallbackException().getCause();
throw new DataAccessException(dataAccessException.getErrorCode(),
"Exception in validateLicense.fetchCustomerAccountDetails::" + e.getMessage(),e);
}
else
throw new DataAccessException(Constants.ERRCODE_AIA_EXCEPTION,
"Exception in validateLicense.fetchCustomerAccountDetails:::" + e.toString(), e);
}
return response;
}
private GetCustomerAccountResponseType aiaClientCommandFallback(String accountNumber, Throwable e)
throws DataAccessException {
logger.error("Inside AIAClientCommandFallback : Error is ::" + e.toString());
if(e instanceof HystrixTimeoutException)
throw new DataAccessException(Constants.ERRCODE_AIA_QUERY_TIMED_OUT,
"Exception in AIAClientCommandFallback::" + e.toString(),e);
else if(e instanceof DataAccessException)
throw (DataAccessException)e;
else
throw new DataAccessException(Constants.ERRCODE_AIA_EXCEPTION,
"Inside AIAClientCommandFallback : Error is ::" + e.toString(), e);
}

Instead of returning something in your mocked fetchCustomerAccount just throw an Exception there via thenThrow:
Mockito.when(service.fetchCustomerAccount(any(GetCustomerAccountType.class))).thenThrow(new RuntimeException("Timeout"));

Related

Missing nested exception

I'm doing some testing of my stateless session beans from a junit class so the flow goes something like this.
Junit test method calls a business method in bean A. This method throws a CustomException.
Bean A business method calls bean B business method. This method also throws a CustomException.
Bean B calls a remote Bean C which throws a BeanCException. Bean B catches an AccountBadFormatException, wraps it in CustomException and throws is back to Bean A.
From Bean A CustomException is rethrown back to JUnit calling code. When I catch CustomException in JUnit and look at it, there is no AccountBadFormatException inside. The cause reads "CustomException" and the stacktrace is gone. But If I look at it in Bean A just before it gets thrown to JUnit the nested exception is there. Why would this happen?
JUnit class:
#Test
public void testGetResult() {
setupContext();
Result result = null;
try {
result = (Result) serviceInterface.getResult("000001", "01011970");
} catch (CustomException e) {
System.out.println("CustomException getCause() in JUnit: " + e.getCause().toString());
fail();
}
assertTrue((result.getReturnCode() == ReturnCode.OK));
}
Bean A:
#Override
public Result getResult(String clientID, String dob) throws CustomException {
Result result = new Result(ReturnCode.ERROR);
boolean isMatched = false;
try {
isMatched = Lookup.getUtilityService().isIdentMatched(clientID, dob);
} catch (CustomException e) {
System.out.println("CustomException getCause() in Bean A: " + e.getCause().toString());
throw e;
}
if (isMatched) {
result.setReturnCode(ReturnCode.OK);
}
return result;
}
Bean B:
#Override
public boolean isIdentMatched(String clientID, String dob) throws CustomException {
IdentRequest request = new IdentRequest(clientID);
ClientSummary response = null;
// retrieve the data
try {
response = getRetriever().getClientSummaryView(request)
.getClientSummary();
} catch (XrefAccountNumberException e) {
throw new CustomException(e.getMessage(), e);
} catch (AccountNotFoundException e) {
throw new CustomException(e.getMessage(), e);
} catch (AccountBadFormatException e) {
throw new CustomException(e.getMessage(), e);
} catch (ExclusiveLockException e) {
throw new CustomException(e.getMessage(), e);
} catch (RemoteException e) {
throw new CustomException(e.getMessage(), e);
} catch (ValidationException e) {
throw new CustomException(e.getMessage(), e);
}
return response.isMismatch();
}
The output of the print statement in Bean A is: "CustomException getCause() in Bean A: ca.gc.cra.iica.iasi.common.exceptions.AccountBadFormatException"
The print statement in JUnit is: "CustomException getCause() in JUnit: ca.gc.cra.fltr.filemyreturn.business.exceptions.CustomException"

Testing methods using JUnit

I am new to JUnit and I have to test a method using JUnit api. One method internall calls another. My test case goes inside the method but while catchign the exception it fails.
Method under test is
public void checkANDCondition( Map<String, Message> messagesMap ) throws EISClientException
{
List<String> codes = getMessageCodes();
if(isAllReturnedMessagesContainCodes(codes, messagesMap))
{
StringBuffer buff = new StringBuffer("All of the specified message codes matched returned errors.");
for(String code: codes )
{
Message message = messagesMap.get(code);
buff.append(message.getMessageCode() + ": " + message.getMessageType() + ": " + message.getMessageText() + " ");
}
throw new EISClientException(buff.toString());
}
}
public boolean isAllReturnedMessagesContainCodes(List<String> codes, Map<String, Message> messagesMap)
{
if(codes!=null)
{
for(String code: codes)
{
if(!messagesMap.containsKey(code))
{
return false;
}
}
}
return true;
}
What I have done so far is
#Test
public void testPostProcess() throws Exception {
clientResponse = mock(ClientResponse.class);
MessageToExceptionPostProcessFilter postProcessFilter = new MessageToExceptionPostProcessFilter();
RetrieveBillingServiceResponse serviceResponse = new RetrieveBillingServiceResponse();caughtException = false;
try {
postProcessFilter.setCondition(ConditionOperator.AND);
List<String> messagesCodes = new ArrayList<String>();
messagesCodes.add("200");
messagesCodes.add("400");
Message message = new Message();
message.setMessageCode("200");
message.setMessageType(MessageTypeEnum.MESSAGE_TYPE_INFO);
message.setMessageText("Service completed successfully");
serviceResponse.setMessages(Arrays.asList(message));
postProcessFilter.setMessageCodes(messagesCodes);
serviceResponse = postProcessFilter.postProcess(serviceResponse, clientResponse);
assertNotNull(serviceResponse.getMessages());
} catch (EISClientException ex) {
caughtException = true;
assertEquals("All of the specified message codes matched returned errors.", ex.getMessage());
}
assertTrue(caughtException);
}
How can I make it pass?
Thanks
#Test(expected = EISCLientException.class)
public void testPostProcess() throws Exception {
...
serviceResponse.getMessages();
fail("Shouldn't reach this point");
}
That way you don't need to catch, with expected if it does not get throw a EISClientException it will fail.
edit: There are two times I can think of where you wouldn't want to use this.
1) You are mocking exceptions that are thrown mock(exception.class);
this i believe then throws some Mockito excpetion and it will not match the expected exception.
2) You are wrapping caught exceptions in your code, and throwing a generic exception. Example of code:
try {
} catch (FileParseException e){
throw new (ProjectFailingException(e, "file is bad");
}
if you have multiple catches and are wrapping them as ProjectFailingExceptions then you may want to catch in the test like this...
#Test ( expected = FileParseException.class)
public void testProcess() {
try {
...
} catch (ProjectFailingException e){
throw e.getCause();
}
Then the proper exception is thrown and you can make sure that process isn't throwing an exception from a a different catch.

Why does object inside a protected method has implementation?

Its the method invokeBackend(String request, HashMap context) .
Why does it have an object named java.security.PrivilegedAction createController = new java.security.PrivilegedAction()
and it has an implementation ? I see it has a run() method which means its a thread.
Does the run method returns "controller"? It returns "controller" to what?
What kind of an implementation is this? An object having implementation code?
3.Whats the primary use of implmentation of the method invokeBackend
Also the object
java.security.PrivilegedAction processRequest = new java.security.PrivilegedAction()
Thanks a lot!
protected static String invokeBackend(String request, HashMap context)
throws CommonModelException {
if (request.equals("")) {
return null;
}
if (logger.isDebugEnabled()) {
logger.debug("request: \r\n" + request);
}
Properties clientAuthenticationEnv = CommonProperties
.getClientAuthenticationProperties();
if (wccClientId == null) {
wccClientId = clientAuthenticationEnv.getProperty(CLIENT_ID);
}
if (wccClientPassword == null) {
wccClientPassword = clientAuthenticationEnv
.getProperty(CLIENT_PASSWORD);
}
controllerHome = getControllerHome();
String response = null;
try {
if (controllerHome == null) {
throw new CommonModelException(ResourceBundleHelper.resolve(
CommonResourceBundleNames.COMMON_STRINGS,
LOG_REMOTE_EXCEPTION));
}
if (isWASImpl) {
java.security.PrivilegedAction createController = new java.security.PrivilegedAction() {
public Object run() {
Object controller = null;
try {
controller = controllerHome.create();
} catch (RemoteException e) {
logger.error(ResourceBundleHelper.resolve(
CommonResourceBundleNames.COMMON_STRINGS,
LOG_REMOTE_EXCEPTION), e);
} catch (CreateException e) {
logger.error(ResourceBundleHelper.resolve(
CommonResourceBundleNames.COMMON_STRINGS,
LOG_FAIL_GET_EJB_INSTANCE), e);
}
return controller;
}
}; // PrivilegedAction
validateSecurityToken();
final DWLServiceController controller = (DWLServiceController) WSSubject
.doAs(subject, createController);
final String req = request;
final HashMap cxt = context;
java.security.PrivilegedAction processRequest = new java.security.PrivilegedAction() {
public Object run() {
Object response = null;
try {
response = (String) controller.processRequest(cxt,
req);
} catch (com.dwl.base.exception.DWLResponseException e) {
response = e.getLocalizedMessage();
} catch (RemoteException e) {
logger.error(ResourceBundleHelper.resolve(
CommonResourceBundleNames.COMMON_STRINGS,
LOG_REMOTE_EXCEPTION), e);
}
return response;
}
}; // PrivilegedAction
validateSecurityToken();
response = (String) WSSubject.doAs(subject, processRequest);
} else {
// DWLServiceController controller = controllerHome.create();
// response = (String) controller.processRequest(context,
// request);
java.security.PrivilegedAction createController = new java.security.PrivilegedAction() {
public Object run() {
Object controller = null;
try {
controller = controllerHome.create();
} catch (RemoteException e) {
logger.error(ResourceBundleHelper.resolve(
CommonResourceBundleNames.COMMON_STRINGS,
LOG_REMOTE_EXCEPTION), e);
} catch (CreateException e) {
logger.error(ResourceBundleHelper.resolve(
CommonResourceBundleNames.COMMON_STRINGS,
LOG_FAIL_GET_EJB_INSTANCE), e);
}
return controller;
}
}; // PrivilegedAction
//reflection invoke to avoid compile dependency on weblogic library
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Class securityClazz = cl.getClass().getClassLoader().loadClass("weblogic.security.Security");
Method runAs = securityClazz.getMethod("runAs", new Class[]{Subject.class, java.security.PrivilegedAction.class});
final DWLServiceController controller = (DWLServiceController) runAs.invoke(securityClazz, new Object[]{subject, createController});
//final DWLServiceController controller = (DWLServiceController) Security.runAs(subject, createController);
final String req = request;
final HashMap cxt = context;
java.security.PrivilegedAction processRequest = new java.security.PrivilegedAction() {
public Object run() {
Object response = null;
try {
response = (String) controller.processRequest(cxt,
req);
} catch (com.dwl.base.exception.DWLResponseException e) {
response = e.getLocalizedMessage();
} catch (RemoteException e) {
logger.error(ResourceBundleHelper.resolve(
CommonResourceBundleNames.COMMON_STRINGS,
LOG_REMOTE_EXCEPTION), e);
}
return response;
}
}; // PrivilegedAction
response = (String)runAs.invoke(securityClazz, subject, processRequest);
//response = (String) Security.runAs(subject, processRequest);
}
} catch (Exception e) {
response = e.getLocalizedMessage();
// for non IBM WebSphere Server, we have one more chance to redo
// lookup for EJB server restart, clear the session first
controllerHome = getControllerHome();
if (controllerHome == null) {
throw new CommonModelException(ResourceBundleHelper.resolve(
CommonResourceBundleNames.COMMON_STRINGS,
LOG_REMOTE_EXCEPTION));
}
try {
DWLServiceController controller = controllerHome.create();
response = (String) controller.processRequest(context, request);
} catch (DWLResponseException e1) {
response = e1.getLocalizedMessage();
} catch (RemoteException e1) {
logger.error(ResourceBundleHelper.resolve(
CommonResourceBundleNames.COMMON_STRINGS,
LOG_REMOTE_EXCEPTION), e1);
throw new CommonModelException(e1);
} catch (CreateException e1) {
logger.error(ResourceBundleHelper.resolve(
CommonResourceBundleNames.COMMON_STRINGS,
LOG_FAIL_GET_EJB_INSTANCE), e1);
throw new CommonModelException(e1);
}
}
if (logger.isDebugEnabled()) {
logger.debug("response: \r\n" + response);
}
return response;
}
The declaration you're looking at is a local variable initialized to reference an instance of an anonymous inner class. The class implemented is PrivilegedAction. The syntax is used when you want to create a one-off implementation of an interface or class that you don't intend to use elsewhere, so there's no point in giving it a name. The code implements the run method from the interface and creates an object implementing that interface, that it assigns to the local variable.
The run method returns a controller object to whoever calls run on it. That isn't shown here, it's passed in as one of the arguments to the runAs method call on this line:
final DWLServiceController controller = (DWLServiceController) runAs.invoke(
securityClazz, new Object[]{subject, createController});
where the code used reflection to look up the runAs method on the class weblogic.security.Security.

How to throw exception from spring batch processor process() method to Spring batch job started method?

I am having the Web-service method to start spring batch job.If any exception occurred in spring batch processing control is coming back till processor process method. But i need the controller to came back to web-service method there i have to catch and code to email that exception.
Web-service method:
public void processInputFiles() throws ServiceFault {
String[] springConfig = { CONTEXT_FILE_NAME };
ApplicationContext context = new ClassPathXmlApplicationContext(springConfig);
try {
setClientInfo();
JobLauncher jobLauncher = (JobLauncher) context.getBean(JOB_LAUNCHER);
Job job = (Job) context.getBean(REMITTANCE_JOB);
jobLauncher.run(job, new JobParameters());
}catch (Exception e) {
String errorMessage = "LockboxService exception:: Could not process Remittance(CSV) files";
final Message message = MessageFactory.createErrorMessage(MyService.class, errorMessage, e);
ErrorSenderFactory.getInstance().send(message, new Instruction[] { Instruction.ERROR_EMAIL });
}
Processor process method:
#Override
public Transmission process(InputDetail remrow) throws ServiceException {
try {
business logic here
}
catch(Exception e) {
throw new Exception("Unable to process row having the int number:");
}
}
Here is startJob which I use the to start the job in web application, Tye to throw specific exception
public boolean StartJob()
throws MyException{
try {
final JobParameters jobParameters = new JobParametersBuilder()
.addLong("time", System.nanoTime())
.addString("file", jobInputFolder.getAbsolutePath())
.toJobParameters();
final JobExecution execution = jobLauncher.run(job,
jobParameters);
final ExitStatus status = execution.getExitStatus();
if (ExitStatus.COMPLETED.getExitCode().equals(
status.getExitCode())) {
result = true;
} else {
final List<Throwable> exceptions = execution
.getAllFailureExceptions();
for (final Throwable throwable : exceptions) {
if (throwable instanceof MyException) {
throw (MyException) throwable;
}
if (throwable instanceof FlatFileParseException) {
Throwable rootException = throwable.getCause();
if (rootException instanceof IncorrectTokenCountException) {
throw new MyException(logMessage, errorCode);
}
if (rootException instanceof BindException) {
BindException bindException = (BindException) rootException;
final FieldError fieldError = bindException
.getFieldError();
final String field = fieldError.getField();
throw new MyException(logMessage, errorCode);
}
}
}
}
}
} catch (JobExecutionAlreadyRunningException ex) {
} catch (JobRestartException ex) {
} catch (JobInstanceAlreadyCompleteException ex) {
} catch (JobParametersInvalidException ex) {
} catch (IOException ex) {
} finally {
}
return result;
}
If Item processor is as below
#Override
public KPData process(InputDetail inputData) throws MyException {
try {
business logic here
}
catch(Exception e) {
throw new MyException("Some issue");
}
}

How to bypass ClassNotFoundException while ObjectInputStream.readObject?

I'm trying to read a serialized Java file containing instances of classes I don't have in my classpath while reading.
Is there a way (perhaps by writing my own ObjectInputStream?) to ignore those ClassNotFoundException and replace the corresponding object of the stream by null ?
The object I want to read is similar to this one :
public class Log {
private String someField;
private Throwable throwable;
}
Actually, that Log object is read, but I don't have in my classpath the concrete class of some Log.throwable values. I would want that in that case, the throwable field value would be null but I want my Log object with the other fields read.
If I catch the exception, I couldn't even have my Log object.
Actually, I have tried multiple way to do this (extend ObjectInputStream and implement ObjectInputStream.readClassDescriptor() in order to return a Proxy of an ObjectStreamClass which would return null for default method ObjectStreamClass.getResolveException(), using Javassist because JDK cannot proxify classes, but the problem is : ObjectStreamClass cannot be instantiated outside of java.io package).
But I finally found a (rather ugly) way to do this :
public class DecompressibleObjectInputStream extends ObjectInputStream {
private static Logger logger = LoggerFactory.getLogger(DecompressibleObjectInputStream.class);
public DecompressibleObjectInputStream(InputStream in) throws IOException {
super(in);
try {
// activating override on readObject thanks to https://stackoverflow.com/a/3301720/535203
Field enableOverrideField = ObjectInputStream.class.getDeclaredField("enableOverride");
enableOverrideField.setAccessible(true);
Field fieldModifiersField = Field.class.getDeclaredField("modifiers");
fieldModifiersField.setAccessible(true);
fieldModifiersField.setInt(enableOverrideField, enableOverrideField.getModifiers() & ~Modifier.FINAL);
enableOverrideField.set(this, true);
} catch (NoSuchFieldException e) {
warnCantOverride(e);
} catch (SecurityException e) {
warnCantOverride(e);
} catch (IllegalArgumentException e) {
warnCantOverride(e);
} catch (IllegalAccessException e) {
warnCantOverride(e);
}
}
private void warnCantOverride(Exception e) {
logger.warn("Couldn't enable readObject override, won't be able to avoid ClassNotFoundException while reading InputStream", e);
}
#Override
public void defaultReadObject() throws IOException, ClassNotFoundException {
try {
super.defaultReadObject();
} catch (ClassNotFoundException e) {
logger.warn("Potentially Fatal Deserialization Operation.", e);
}
}
#Override
protected Object readObjectOverride() throws IOException, ClassNotFoundException {
// copy of JDK 7 code avoiding the ClassNotFoundException to be thrown :
/*
// if nested read, passHandle contains handle of enclosing object
int outerHandle = passHandle;
try {
Object obj = readObject0(false);
handles.markDependency(outerHandle, passHandle);
ClassNotFoundException ex = handles.lookupException(passHandle);
if (ex != null) {
throw ex;
}
if (depth == 0) {
vlist.doCallbacks();
}
return obj;
} finally {
passHandle = outerHandle;
if (closed && depth == 0) {
clear();
}
}
*/
try {
int outerHandle = getObjectInputStreamFieldValue("passHandle");
int depth = getObjectInputStreamFieldValue("depth");
try {
Object obj = callObjectInputStreamMethod("readObject0", new Class<?>[] {boolean.class}, false);
Object handles = getObjectInputStreamFieldValue("handles");
Object passHandle = getObjectInputStreamFieldValue("passHandle");
callMethod(handles, "markDependency", new Class<?>[] {int.class, int.class}, outerHandle, passHandle);
ClassNotFoundException ex = callMethod(handles, "lookupException", new Class<?>[] {int.class}, passHandle);
if (ex != null) {
logger.warn("Avoiding exception", ex);
}
if (depth == 0) {
callMethod(getObjectInputStreamFieldValue("vlist"), "doCallbacks", new Class<?>[] {});
}
return obj;
} finally {
getObjectInputStreamField("passHandle").setInt(this, outerHandle);
boolean closed = getObjectInputStreamFieldValue("closed");
if (closed && depth == 0) {
callObjectInputStreamMethod("clear", new Class<?>[] {});
}
}
} catch (NoSuchFieldException e) {
throw createCantMimicReadObject(e);
} catch (SecurityException e) {
throw createCantMimicReadObject(e);
} catch (IllegalArgumentException e) {
throw createCantMimicReadObject(e);
} catch (IllegalAccessException e) {
throw createCantMimicReadObject(e);
} catch (InvocationTargetException e) {
throw createCantMimicReadObject(e);
} catch (NoSuchMethodException e) {
throw createCantMimicReadObject(e);
} catch (Throwable t) {
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
}
if (t instanceof IOException) {
throw (IOException)t;
}
throw createCantMimicReadObject(t);
}
}
private IllegalStateException createCantMimicReadObject(Throwable t) {
return new IllegalStateException("Can't mimic JDK readObject method", t);
}
#SuppressWarnings("unchecked")
private <T> T getObjectInputStreamFieldValue(String fieldName) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
Field declaredField = getObjectInputStreamField(fieldName);
return (T) declaredField.get(this);
}
private Field getObjectInputStreamField(String fieldName) throws NoSuchFieldException {
Field declaredField = ObjectInputStream.class.getDeclaredField(fieldName);
declaredField.setAccessible(true);
return declaredField;
}
#SuppressWarnings("unchecked")
private <T> T callObjectInputStreamMethod(String methodName, Class<?>[] parameterTypes, Object... args) throws Throwable {
Method declaredMethod = ObjectInputStream.class.getDeclaredMethod(methodName, parameterTypes);
declaredMethod.setAccessible(true);
try {
return (T) declaredMethod.invoke(this, args);
} catch (InvocationTargetException e) {
throw e.getCause();
}
}
#SuppressWarnings("unchecked")
private <T> T callMethod(Object object, String methodName, Class<?>[] parameterTypes, Object... args) throws Throwable {
Method declaredMethod = object.getClass().getDeclaredMethod(methodName, parameterTypes);
declaredMethod.setAccessible(true);
try {
return (T) declaredMethod.invoke(object, args);
} catch (InvocationTargetException e) {
throw e.getCause();
}
}
}
Then I overrode the ObjectInputStream.readClassDescriptor() in order to ignore differences between serialVersionUID also (as described in that answer) and I've got an ObjectInputStream which can read nearly everything !
I don't think there is a way to do this ... apart from cloning and modifying the Java serialization implementation.
Certainly, readObject and readResolve hooks won't help, because they rely on methods of the class that you cannot load.

Categories