I am working on an requirement(Spring mvc architecture, java 8), actually it's kind of fix ,where I have to filter the data on basis on an condition.
I can filter data in DAO layer that is by applying joins in data base query . But the problem is there are lots of method where I am supposed to apply this condition for filtering data.
First I thought :
I should define an instance variable in DAO class and set this variable via method from Action class(this condition data supposed to come from Action to DAO layer). But it seems very odd and general practice doesn't allow it too.
Other I can search all the method and change the parameter which is also not good practice.
I am not sure how to achieve this.
Does anyone have any idea about this?
any pattern or any suitable method.
E.g.
ActionClass{
doSOmething(){
variable condition = object.getCondotion();
variable someData = serviceClass.fetchDataOnCondtion(condition);
}
}
ServiceClass{
fetchDataAOnCondtion(variable condition){
dataObjectDAO.fetchDataAOnCondtion(condition);
}
fetchDataBOnCondtion(variable condition){
dataObjectDAO.fetchDataBOnCondtion(condition);
}
}
someDataObjectDAO{
fetchDataAOnCondtion(condition){};
fetchDataBOnCondtion(condition){};
fetchDataCOnCondtion(condition){};
fetchDataDOnCondtion(condition){};
}
here in DAO class I am using same condition variable in every method on DAO class , but there are a lot method which is quite tedious to change and also I need to change the interface method def too.
please provide some suggestion how can I solve this problem?
thanks in advance !
Related
I have a a static method in some legacy code, which is called by multiple clients. I obviously have no options to override it, or change behaviour through dependency injection. I am not allowed to modify the existing class.
What I want to do now is change the behaviour (that method - with the same signature and return type) using reflection.
Is it possible ? If not, can any design pattern rescue me ?
Thanks !
EDIT : There is some confusion on what can I change/modify. I cannot change any existing class/method - but I can add more classes to the project. The best I can do with the existing classes is annotate them. This is all done to avoid breaking anything in the existing code - which means a complete round of testing for a big project.
EDIT 2 : java.lang.Instrumentation is not available for Android - or else it sounds like a good fit !
Sounds like a weird requirement...
Anyway, reflection does not allow you to change code behaviour, it can only explore current code, invoke methods and constuctors, change fields values, that kind of things.
If you want to actually change the behaviour of a method you would have to use a bytecode manipulation library such as ASM. But this will not be very easy, probably not a good idea...
Patterns that might help you :
If the class is not final and you can modify the clients, extend the existing class and overload the method, with your desired behaviour. Edit : that would work only if the method were not static !
Aspect programming : add interceptors to the method using AspectJ
Anyway, the most logical thing to do would be to find a way to modify the existing class, work-arounds will just make your code more complicated and harder to maintain.
Good luck.
I guess you could have a look at Instrumentation class which have a method redefineClasses(ClassDefintion classDefinition).
The redefinition may change method bodies, the constant pool and attributes. The redefinition must not add, remove or rename fields or methods, change the signatures of methods, or change inheritance.
Hope this helps.
References: Javadoc
You can change method behaviour via Java's dynamic proxies mechanism. See this guide.
It will proxied all object methods. You can redefine only some methods by method name, like:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("put")) { // example for map
methods.get(method.getName()).invoke(target, args);
args[0] = "second"; // put again with "second" key
Object result = methods.get(method.getName()).invoke(target, args);
return result;
}
if (method.getName().equals("get")) { // example for map
System.out.println("Method get"); // you implementation
return methods.get(method.getName()).invoke(target, args);
}
return methods.get(method.getName()).invoke(target, args); // just do what initial method do
}
I have a a static method in some legacy code, which is called by multiple clients. I obviously have no options to override it, or change behaviour through dependency injection. I am not allowed to modify the existing class.
What I want to do now is change the behaviour (that method - with the same signature and return type) using reflection.
Is it possible ? If not, can any design pattern rescue me ?
Thanks !
EDIT : There is some confusion on what can I change/modify. I cannot change any existing class/method - but I can add more classes to the project. The best I can do with the existing classes is annotate them. This is all done to avoid breaking anything in the existing code - which means a complete round of testing for a big project.
EDIT 2 : java.lang.Instrumentation is not available for Android - or else it sounds like a good fit !
Sounds like a weird requirement...
Anyway, reflection does not allow you to change code behaviour, it can only explore current code, invoke methods and constuctors, change fields values, that kind of things.
If you want to actually change the behaviour of a method you would have to use a bytecode manipulation library such as ASM. But this will not be very easy, probably not a good idea...
Patterns that might help you :
If the class is not final and you can modify the clients, extend the existing class and overload the method, with your desired behaviour. Edit : that would work only if the method were not static !
Aspect programming : add interceptors to the method using AspectJ
Anyway, the most logical thing to do would be to find a way to modify the existing class, work-arounds will just make your code more complicated and harder to maintain.
Good luck.
I guess you could have a look at Instrumentation class which have a method redefineClasses(ClassDefintion classDefinition).
The redefinition may change method bodies, the constant pool and attributes. The redefinition must not add, remove or rename fields or methods, change the signatures of methods, or change inheritance.
Hope this helps.
References: Javadoc
You can change method behaviour via Java's dynamic proxies mechanism. See this guide.
It will proxied all object methods. You can redefine only some methods by method name, like:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("put")) { // example for map
methods.get(method.getName()).invoke(target, args);
args[0] = "second"; // put again with "second" key
Object result = methods.get(method.getName()).invoke(target, args);
return result;
}
if (method.getName().equals("get")) { // example for map
System.out.println("Method get"); // you implementation
return methods.get(method.getName()).invoke(target, args);
}
return methods.get(method.getName()).invoke(target, args); // just do what initial method do
}
I'm trying to fix some existing junit/mockito tests that I've had to alter due to a re-write to use Dao's.
So I have this argument captor :-
ArgumentCaptor<CustomerDao> customerDaoCaptor = ArgumentCaptor.forClass(CustomerDao.class);
and I've used this approach before to get the (customer) object so that I can perform more tests on it. I would usually use it like this :-
verify(customerDao, times(1)).saveOrUpdate(customerDaoCaptor.capture());
so that I can then run tests like :-
Customer customerActual = (Customer) customerDaoCaptor.getAllValues().get(0);
assertEquals("PRE", customerActual.getExistingCustomer());
However in this instance I'm not calling the saveOrUpdate method (that the captor is bound to), but another Dao method that takes a unique key as a parameter that ultimately updates the customer record by using sql - ie it doesnt use the parent object's (Hibernate) saveOrUpdate method.
I know that I can test that its called, eg :-
inOrder.verify(customerDao, times(1)).updateRegisterStatusToCurrentByCustomerNumber(CUSTOMER_NUMBER);
so I'm trying to somehow assign/bind the captor to the 'updateRegisterStatus....' method, but I cant seem to find a way to do it, mainly because that method must take a string param, customer_number.
So in essence I'm trying to do this :-
inOrder.verify(customerDao, times(1)).updateRegisterStatusToCurrentByCustomerNumber(CUSTOMER_NUMBER).customerDaoCaptor.capture()
which obviously doesn't work...
As a lot of googling hasn't helped me, I'm guessing that I'm doing it completely wrong.
Update - #SpaceTrucker
I've tried the following code as you suggested :-
CapturingMatcher<String> capturingMatcher = new CapturingMatcher<String>();
verify(customerDao, times(1)).updateRegisterStatusToCurrentByCustomerNumber(
argThat(
org.hamcrest.Matchers.allOf(capturingMatcher, org.hamcrest.Matchers.notNullValue())
)
);
List<String> values = capturingMatcher.getAllValues();
based on my Dao implementation :-
public void updateRegisterStatusToCurrentByCustomerNumber(String customerNumber)
and it does pass the test successfully, in that it doesn't fail, but it doesnt do everything what I need it to. The ideal goal here is to somehow get an object representing the updated customer object - eg :-
Customer customerActual = (Customer) values.get(0);
assertEquals("value", customerActual.getExistingCustomer());
However the values object is empty and on debugging the test I can confirm that the method in question is being called.
Apologies in advance if there's something trivial that I've missed here, and once again, thanks for all your help!
This problem seems to more difficult than first thought about. See below for more details on this.
The Matcher instance Mockito does need to see has to implement the CapturesArguments interface. So the solution is to implement an AndMatcher that will delegate to its child matchers and implements CapturesArguments. It will delegate to all child matchers that also implement CapturesArguments when CapturesArguments.captureFrom(Object). Please note that CapturesArguments is a Mockito internal interface.
The following solution does not work,
because the Matcher instance Mockito sees, doesn't implement the CapturesArguments interface and therefore won't delegate the argument capturing to the CapturingMatcher.
The ArgumentCaptor uses a CapturingMatcher internally. So you could use Mockito.argThat with a combined matcher that will consist of a CapturingMatcher and any other matcher you like.
For example given the interface
public interface ProductService {
List<Product> getProductsForCategory(Category category);
}
then we can do the following:
import org.hamcrest.Matchers;
// ...
CapturingMatcher<Category> capturingMatcher = new CapturingMatcher<Category>();
Mockito.verify(productService).getProductsForCategory(Mockito.argThat(Matchers.allOf(capturingMatcher, Matchers.notNullValue())));
List<Category> values = capturingMatcher.getAllValues();
You could also implement your own ArgumentCaptor with a capture method that will take an additional matcher instance.
Your question isn't entirely clear, but I'm getting the following points from it:
You have a mock of a CustomerDao.
Your test (indirectly) calls the updateRegisterStatusToCurrentByCustomerNumber() method of this mock, passing a String identifier to it.
updateRegisterStatusToCurrentByCustomerNumber() does something internally to a Customer object.
You want to test things about the Customer object in question.
If these are correct, then you have a fundamental misunderstanding of how mocks work. That internal code that does something to a Customer object? In this test, that code doesn't exist. It's never called. The mock version of CustomerDao responds to your updateRegisterStatusToCurrentByCustomerNumber() call by simply returning what your test setup code told it to, whether that's null, a carefully crafted sample object, or another mock. It never invokes the actual CustomerDao code because the whole point of a mock is to make your test not be dependent on that code, so that bugs in that code don't cascade test failures throughout the dependency tree.
To test the internal behavior of CustomerDao.updateRegisterStatusToCurrentByCustomerNumber(), you will need to create separate tests that directly call CustomerDao methods on a non-mock CustomerDao, with everything else being mocks.
I am working on my struts2 application to solve Parameter tampering problem. I heard this can be solved by implementing ParameterNameAware interface in my actions, but I haven't find a best example explaining this condition. Can anyone provide me a good example on how to use ParameterNameAware. Quick answers will be really appreciated.
The wholde idea about this interface is to maintain a list of valid parameter names and there by rejecting any request parameters that are not in this list(whitelist).This is really helpfull in situations where a hacker tries to include unwanted form field values as a hidden variable that are likely to execute in certain situations.For example, include so many form fiels varialbles (>10000 etc) that may create Denial Of serice on server side.
Once you have implemented this, you can immediatly reject any unwanted parameters in the current request scope or you can take a better control of this situation.
Probable implementation :
Implement the ParameterNameAware interface and override its acceptableParameterName method as follows:
public boolean acceptableParameterName(String parameterName) {
boolean allowedParameterName = true ;
if ( parameterName.contains("session") || parameterName.contains("request") ) {
allowedParameterName = false ;
}
return allowedParameterName;
}
You need to implement this interface in your form bean that is having getter and setter methods in it. In this particular example, if the current request contains any form field variable like request or session, then it is a failure scenario.This is just a typical example here. There is a complete documentation in this link
Class ParametersInterceptor
I am implementing a sort of ORM in Java. I am trying to do a static find method that is only in the parent class. Let me get to the point:
public class DB {
public static Object find (int id) {
// i want to return anew instance of the calling subclass
}
}
public class Item extends DB {
// nothing here
}
public class Test {
public static void main () {
Item i = (Item) Item.find(2);
...
}
}
I don't know how to have the find method know which of its inherited class is calling it, so that i can return the right instance (and maybe call the right constructor, etc.) And the inherited class could be anything, no limit.
I've tried stacktrace, but it's only traced from Test to DB.
Any ideas?
Thank you everyone!
Static methods are not inherited, so you can't do this. A common approach to this problem (not including using one of tons of available ORM solutions) is to split your class hierarchy into two:
"Entity" (e.g. classes representing your actual data)
and "DAO" (Data Access Object) - classes that contain methods to manipulate data persistence.
A word to the wise: It's probably a bad idea to try and implement your own ORM. Projects like hibernate have covered this task in great detail, so if you roll your own you are likely to reinvent the wheel and possibly attempt to solve problems that have already been solved.
More on topic, ChssPly76 is correct in that you cannot accomplish this because of how static methods are handled in Java. When the VM loads the bytecode for the static method invocation, it will perform a lookup to find where the method actually is located. It won't find it on the Item class, so it will instead bind the call to DB.find.
However! It may be possible to achieve what you are trying to do with some bytecode wrangling. Viewing the bytecode (using javap -c) for the static method call in your example, we get the following:
invokestatic Method Item.find:(I)Ljava/lang/Object
Thus, once your call reaches DB.find, you could follow the stacktrace back to the callsite, and then inspect the bytecode at the callsite to retrive the actual target of the call. In theory, anyway, as I haven't seen this myself in practice. Also, beware of hacking bytecode like this, for here be dragons.
Kudos for identifying the active record pattern, and wanting to use it in Java. I do agree it's a design pattern that makes more sense than most DB access patterns found in Java, and it's one of the strengths of Ruby and PHP.
I think you may find the "Generic DAO" article at IBM developerworks useful.
Short: use Generics wisely.