Mocking java.lang.Class getDeclaredMethod(String name, ...Class args) with Mockito not working - reflection

I am trying to mock the getDeclaredMethod on a java .class object of a certain defined java type:
AccessRulesMethods accessRulesMock = mock(AccessRulesMethods.class);
Method mockMethod = mock(Method.class);
when(accessRulesMock.getClass().getDeclaredMethod(param.getValue(), String.class, BigInteger.class)).thenReturn(mockMethod);
but I get the following exception:
java.lang.NoSuchMethodException: myOwnPackage.AccessRulesMethods.methodName(java.lang.String, java.math.BigInteger)
at java.lang.Class.getDeclaredMethod(Class.java:2130)
Lokking into java.lang.Class at line 2130 it seems that the method is not mocked at all. I found in another discussion here that this is the correct way but with no examples...
Anyone knows how can I manage to get what I need?
Thanks a lot,
Saverio
Business logic:
try {
Method method = AccessRulesMethods.class.getDeclaredMethod(name, String.class, BigInteger.class);
String parameterName = Arrays.asList(method.getParameters()).get(0).getName();
Field inputField = input.getClass().getDeclaredField(parameterName);
inputField.setAccessible(true);
String parameterValueFromInput = (String) inputField.get(input);
AccessRulesMethods accessRulesInstance = beanFactory.getBean(AccessRulesMethods.class);
methodOutput = (MethodOutput) method.invoke(accessRulesInstance, parameterValueFromInput, input.getIdBp());
}catch (InvocationTargetException ite){
throw ite.getTargetException();
}catch (NoSuchMethodException | IllegalAccessException | NoSuchFieldException e) {
throw new CoreApplicationException("Errore tecnico: invocazione metodo fallita", ErrorConstant.getLocalErrorKey(ErrorConstant.LOCAL_ERROR_CODE_ERRVISREFL001), HttpStatus.INTERNAL_SERVER_ERROR);
}
I have a bean with some methods: AccessRulesMethod. I get method names from a table in a db and the I call this methods with reflection in a given order. In order to call these method, first I get the name of the required parameter (the second one is fixed) and then I pass this parameter from the input to the API, also with reflection

Related

Around Advice not working when dependent on response from other REST service

I am working with Spring AOP to define a common fallback method instead of duplicating code.
I used #Around as I have to return the object from Aspect.I am trying to decide #Around advice depending on the response returned,but not able to do so.
Here is my controller:
#RequestMapping(value = "/add/employee", method = RequestMethod.GET)
public EmployeeResponse addEmployee(#RequestParam("name") String name, #RequestParam("empId") String empId) {
EmployeeResponse employeeResponse=employeeService.createEmployee(name, empId);
return employeeResponse;
}
createEmployee in the service class is used to call another endpoint to insert some data.I want to decide my advice based on the employeeResponse but not able to do so.
I tried #AfterReturning also,but I can't return the object if I use that.
Below is my aspect class:
#Around(value = "execution(* com.test.service.EmployeeService.*(..)) and args(name,empId)")
public Object getAllAdvice2(ProceedingJoinPoint pjp, String name,String empId) throws Throwable {
System.out.println("Inside Aspect");
Object[] arguments = pjp.getArgs();
if (!checkForPath()) {
return pjp.proceed();
}
System.out.println("Call Second path please!!");
return arguments;
}
private boolean checkForPath() {
HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.getResponse();
return response.getStatus()==501?true:false;
}
}
I did use HttpServletResponse and RequestContextHolder to get the context but seems it will take the present context i.e. "/add/employee".
How can I return the actual status from the checkForPath () (since I don't need to call pjp.proceed for every status code returned) so that I can execute the line System.out.println("Call Second path please!!"); depending on my error code.
Can anyone pls suggest where it is going wrong?
Your aspect code is quite chaotic and does not make much sense:
You are trying to check for a response before calling proceed(), as R.G said. Use something like EmployeeResponse response = (EmployeeResponse) proceed() instead, inspect the response and then decide what to do next.
You already bind the method parameters to name and empId, there is no need to use pjp.getArgs().
return arguments does not make sense because you ought to return an EmployeeResponse object (either the original result or another one), not the array of method arguments.

Java 8: convert lambda to a Method instance with closure included

(This is difficult to search because results are all about "method reference")
I want to get a Method instance for a lambda expression for use with a legacy reflection-based API. The clousure should be included, so calling thatMethod.invoke(null, ...) should have the same effect as calling the lambda.
I have looked at MethodHandles.Lookup, but it only seems to be relevant for the reverse transform. But I guess the bind method may help to include the clousure?
Edit:
Say I have am lambda experssion:
Function<String, String> sayHello = name -> "Hello, " + name;
and I have a legacy framework (SpEL) that has an API like
registerFunction(String name, Method method)
which will call the given Method with no this argument (i.e. Method assumed to be static). So I'll need to get a special Method instance that includes the lambda logic + the clousure data.
In case you don't find an elegant way, here is the ugly way (Ideone). Usual warning when reflection is involved: may break in future releases etc.
public static void main(String[] args) throws Exception {
Function<String, String> sayHello = name -> "Hello, " + name;
Method m = getMethodFromLambda(sayHello);
registerFunction("World", m);
}
static void registerFunction(String name, Method method) throws Exception {
String result = (String) method.invoke(null, name);
System.out.println("result = " + result);
}
private static Method getMethodFromLambda(Function<String, String> lambda) throws Exception {
Constructor<?> c = Method.class.getDeclaredConstructors()[0];
c.setAccessible(true);
Method m = (Method) c.newInstance(null, null, null, null, null, 0, 0, null, null, null, null);
m.setAccessible(true); //sets override field to true
//m.methodAccessor = new LambdaAccessor(...)
Field ma = Method.class.getDeclaredField("methodAccessor");
ma.setAccessible(true);
ma.set(m, new LambdaAccessor(array -> lambda.apply((String) array[0])));
return m;
}
static class LambdaAccessor implements MethodAccessor {
private final Function<Object[], Object> lambda;
public LambdaAccessor(Function<Object[], Object> lambda) {
this.lambda = lambda;
}
#Override public Object invoke(Object o, Object[] os) {
return lambda.apply(os);
}
}
Well, lambda expressions are desugared into methods during compilation and as long as they don’t capture this (don’t access non-static members), these methods will be static. The tricky part is to get to these methods as there is no inspectable connection between the functional interface instance and its target method.
To illustrate this, here the simplest case:
public class LambdaToMethod {
public static void legacyCaller(Object arg, Method m) {
System.out.println("calling Method \""+m.getName()+"\" reflectively");
try {
m.invoke(null, arg);
} catch(ReflectiveOperationException ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) throws URISyntaxException
{
Consumer<String> consumer=s -> System.out.println("lambda called with "+s);
for(Method m: LambdaToMethod.class.getDeclaredMethods())
if(m.isSynthetic() && m.getName().contains("lambda")) {
legacyCaller("a string", m);
break;
}
}
}
This works smoothly as there is only one lambda expression and hence, one candidate method. The name of that method is compiler specific and may contain some serial numbers or hash codes, etc.
On kludge is to make the lambda expression serializable and inspect its serialized form:
static Method lambdaToMethod(Serializable lambda) {
for(Class<?> cl=lambda.getClass(); cl!=null; cl=cl.getSuperclass()) try {
Method m=cl.getDeclaredMethod("writeReplace");
m.setAccessible(true);
try {
SerializedLambda sl=(SerializedLambda)m.invoke(lambda);
return LambdaToMethod.class.getDeclaredMethod(sl.getImplMethodName(),
MethodType.fromMethodDescriptorString(sl.getImplMethodSignature(),
LambdaToMethod.class.getClassLoader()).parameterArray());
} catch(ReflectiveOperationException ex) {
throw new RuntimeException(ex);
}
} catch(NoSuchMethodException ex){}
throw new AssertionError();
}
public static void main(String[] args)
{
legacyCaller("a string", lambdaToMethod((Consumer<String>&Serializable)
s -> System.out.println("first lambda called with "+s)));
legacyCaller("a string", lambdaToMethod((Consumer<String>&Serializable)
s -> System.out.println("second lambda called with "+s)));
}
This works, however, serializable lambdas come at a high price.
The simplest solution would be to add an annotation to a parameter of the lambda expression to be found when iterating over the methods, however, currently, javac doesn’t store the annotation properly, see also this question about this topic.
But you may also consider just creating ordinary static methods holding the code instead of a lambda expression. Getting a Method object for a method is straight-forward and you still can create a functional interface instance out of them using method references…
Since the question mentions SpEL specifically (and I found the question when also working with SpEL), an alternative way to add a custom function to the evaluation context without using Method references is to add a custom MethodResolver (javadoc, GitHub) to the StandardEvaluationContext. A benefit of this approach is that one can add both static and non-static methods to the evaluation context using it, where only static methods could be added using the registerFunction approach.
The code to add a custom MethodResolver to the StandardEvaluationContext is fairly straightforward. Below is an executable example showing how to do so:
public static void main(String[] args) throws Exception {
Function<String, String> sayHello = name -> "Hello, " + name;
// The evaluation context must have a root object, which can be set in the StandardEvaluationContext
// constructor or in the getValue method of the Expression class. Without a root object, the custom
// MethodResolver will not be called to resolve the function.
Object rootObject = new Object();
StandardEvaluationContext standardEvaluationContext = new StandardEvaluationContext(rootObject);
// Add the custom MethodResolver to the evaluation context that will return a MethodExecutor that
// Spring can use to execute the sayHello function when an expression contains "sayHello('<any string>')".
standardEvaluationContext.addMethodResolver((context, targetObject, methodName, argumentTypes) -> {
MethodExecutor methodExecutor = null;
if (methodName.equals("sayHello")
&& argumentTypes.size() == 1
&& String.class.isAssignableFrom(argumentTypes.get(0).getObjectType())
) {
methodExecutor = (innerContext, target, arguments) -> {
final String name = arguments[0].toString();
return new TypedValue(sayHello.apply(name));
};
}
return methodExecutor;
});
// Create an expression parser, parser the expression, and get the evaluated value of the expression.
SpelExpressionParser expressionParser = new SpelExpressionParser();
Expression expression = expressionParser.parseExpression("sayHello('World!')");
String expressionValue = expression.getValue(standardEvaluationContext, String.class);
// Output the expression value, "Hello, World!", to the console.
System.out.println(expressionValue);
}
The value of the expression that was output to the console by executing the above code was:
Hello, World!
Note that when using a MethodResolver to add a function to the evaluation conext, the function should not be prefixed with a # in the expression string. This is a major difference between using the MethodResolver and using the registerFunction method to add a function to the evaluation context.
sayHello('World!') // will work!
#sayHello('World!') // will not work!
Keep this in mind if you are considering migrating an existing solution from using the registerFunction approach to using the MethodResolver approach.

FakeMessageContext throws NullReferenceException

I'm trying to write unit test for my saga. I have used SagaFixture to host my Saga and using FakeBus. I have also used FakeMessageContext because, in a Saga exectution I'm using MessageContext to get return address.
Now, when I'm trying to call Handle method on Fixture, it throws exception of type NullReferenceException.
Pasting code below:
SearchSaga
public class SearchSaga : Saga<SearchSagaData>, IAmInitiatedBy<PersonRequested>, IHandleMessages<PersonSearchCompleted>
{
public void Handle(PersonRequested message)
{
Data.Id = new Guid(message.MessageId);
Data.ReturnAddress = MessageContext.GetCurrent().ReturnAddress;
Bus.Publish(message);
}
}
SagaUnitTest
[Test]
public void PublishResponseOfTypeSearchPersonRequest()
{
var bus = new FakeBus();
var saga = new SearchSaga(bus);
var fixture = new SagaFixture<SearchSagaData>(saga);
FakeMessageContext.Reset();
var fakeContext = MockRepository.GenerateMock<IMessageContext>();
fakeContext.Stub(s => s.ReturnAddress).Return("queuename");
fakeContext.Stub(s => s.Headers).Return(new Dictionary<string, object>());
// act
using (FakeMessageContext.Establish(fakeContext))
{
fixture.Handle(new PersonRequested {MessageId = Guid.NewGuid().ToString(), Query = "Abc"});
}
var sentRequests = bus.PublishedMessages.OfType<SearchPersonRequest>().ToList();
Assert.That(sentRequests.Count, Is.EqualTo(1));
}
Error Stacktrace:
at Rebus.SagaContext..ctor(Guid id)
at Rebus.Bus.Dispatcher.DispatchToHandler[TMessage](TMessage message, IHandleMessages1 handler) at Rebus.Testing.SagaFixture1.Handle[TMessage](TMessage message)
The exception is caused by the fact that your IMessageContext mock has a null value on the Items property. The thrown exception is just pretty bad, but I'll make sure that the reported error gets better in the future.
For now, you can fix the situation by setting up a an items dictionary like so:
fakeContext.Stub(s => s.Items).Return(new Dictionary<string, object>());
Moreover, instead of using MessageContext.GetCurrent() to get to the message context inside your handler, you should take advantage of the fact that all Rebus' IoC container adapters ensure that you can have an IMessageContext injected into all of your handler instances.
This way, there's no need to use FakeMessageContext in your unit tests.

Object reference not set to an instance of an object in Session

I am getting an error in this line of code Session.Linq<Employees>() :
" An object reference is required for non-static field,method, or property 'System.Web.UI.Page.Session.get'.
This is my code :
public static object GetData(Dictionary<string, object> tableParams)
{
IQueryable<Employees> Employee = Session.Linq<Employees>();
if (tableParams.ContainsKey("sEcho"))
{
var parser = new DataTableParser<Employees>(tableParams, Employee);
return parser.Parse();
}
return Employee;
}
If I use HttpContext.Current.Session.Linq<Employees>();
then i get:
'System.Web.SessionState.HttpSessionState' does not contain a definition for 'Linq' and no extension method 'Linq' accepting a first argument of type 'System.Web.SessionState.HttpSessionState' could be found '
What do i need to do to get this to work? Am I missing a namespace for Linq with regard to Session?I am using System.Linq and System.Linq.Expression.
I think you're misunderstanding something. What you're trying to do doesn't have anything to do with Linq, at least not in the context of retrieving the object from session.
You need to retrieve the object from session and unbox it:
var list = Session["MyList"] as List<int>;
if (list != null)
{
//the list was found and you can start using it here
}

Building a single entry point to a WCF service: need unified approach to return objects and collections

Subject says it all: I'm creating a secure and generic wrapper to access a WCF service transparently.
A little background:
what I have done is that I've created similar business classes definition both on server and client. The server-side contains the actual logic while the client side contains only method definitions. Additionally, the client-side classes derive from a SecureFactory which implements a Call method. The body of every method of each derived class contains only a call to Call method. This Call method is responsible for invoking the server service passing such things as to the type of business class and which of its method to invoke to perform the requested operation.
This approach is being designed in order to simplify security checks by restricting passing of security information to only between SecureFactory and Server service. There are tuns of other benefits which you most of already aware of.
Now here's the issue: I'm stuck at as to how to return objects (especially arrays of objects) from Server to Call method?
The server may return a single business object (DataContract applied) as well as list of such objects. Since it's a generic approach, I have only Object to be used as return type. Following is the Call method
public object Call(params object[] parameters)
{
var mb = (new StackFrame(1).GetMethod());
using (Proxy.ServerClient server = new Security.BO.Proxy.ServerClient())
{
try
{
if (((MethodInfo)mb).ReturnType.IsGenericType)
{
var response = server.InvokeForList(SecurityManager.Current.SID, SecurityManager.Current.Token, mb.DeclaringType.ToString(), mb.Name, parameters);
return response.Result.ToList();
}
else
{
var response = server.Invoke(SecurityManager.Current.SID, SecurityManager.Current.Token, mb.DeclaringType.ToString(), mb.Name, parameters);
return response.Result;
}
}
catch (Exception ex)
{
System.Diagnostics.Debugger.Break();
}
}
return null;
}
server methods:
public CollectionResponse InvokeForList(string SID, string token, string type, string method, object[] parameters)
{
// Validation here
var t = assemblyBO.GetType(type, true);
object BO = Activator.CreateInstance(t);
var mi = t.GetMethod(method);
if (mi == null)
throw new MethodNotImplementedException("Method " + method + " could not be found on type " + t.ToString());
object res = mi.Invoke(BO, parameters);
// Convert list to t[]
object list = res.GetType().GetMethod("ToArray").Invoke(res, new object[0]);
// Error here! cannot convert t[] into object[]
return new CollectionResponse((object[])list);
}
The other method Invoke(...) is similar accept it returns Response object instead of CollectionResponse.
Here's the CollectionResponse class: (Response is similar:just it takes only one object)
[DataContract]
public class CollectionResponse
{
[DataMember]
private Object[] _result;
public Object[] Result
{
get
{
return _result;
}
}
public CollectionResponse(Object[] result)
{
this._result = result;
}
}
Initially I was thinking to have only one Invoke for both lists and singleton – but failed with "Connection was closed unexpectedly." still I'm not able to achieve – how can I convert T[] into object[].
Do you have any suggestion to improve it, or any other way of achieving the same?
Thanks
I can see an immediate problem here. You are using reflection which is far less perfromant than the direct call.
For me, that is enough not to follow this route.

Resources