possible to check cross fields constraint in the middle of method - java

We have a service class in Java 8 SpringBoot application that needs to check if a field of object A matches object B passed in as a method parameter. It would have worked beautifully using ConstraintValidator if all method signatures took Object A & Object B as parameters.
Method in service class:
#Override
#MyCheck
public String serviceDoLogic(Object B, Object A) {
......
}
Validator class:
#SupportedValidationTarget(ValidationTarget.PARAMETERS)
public class MyCheckValidator implements ConstraintValidator<MyCheck, Object[]> {
#Override
public boolean isValid(
Object[] value,
ConstraintValidatorContext context) {
if( value.length <2 ) {
return true;
}
if ( ! value[0].equals(value[1].myField()) {
return false;
}
return true;
}
}
Unfortunately, for some methods in the service class, it can only take a String identifier for Object A (as it is the only thing known at the time), and within the service, it needs to call DAO to get Object A. Thus the constraint cannot be triggered for them.
Any solution, other than having the check logic embedded in every method that needs it, to get it done in an elegant way? Hope I explain it well
Many thanks in advance

Related

void method refactoring with multiple checks

I have this method:
public void validate(param1, pararm2, param3 ...) {
if(check1)
add error
return
if check2
add error
return
getDbObject
check3
exception
return
There is another use case where along with the above checks, if check1 and check2 are passed then after check3 the db object should be returned.
What should be the best practice for implementing this?
Should I write a new method with the same checks and return the db object after check3, or add more parameters and simplify the existing method?
I read the best practice is to have a maximum of 5 parameters, so if we add more parameters eventually the first method call will have 8-9 parameters
and if we reduce the number of parameters then it will require more checks (if-statements) on every call which is also against OOPs basic principles.
So is there an alternate solution?
I would rewrite to use Exceptions, intentionally returning null isn't that helpful to the caller, perhaps like this:
public DbObjectType validate(param1, param2, ...) throws Check1FailedException, Check2FailedException, Check3FailedException {
check1();
check2();
check3();
return getDbObject();
}
private check1() throws Check1FailedException() {
//DoCheck and throw Exception if failed
}
private check2() throws Check2FailedException() {
//DoCheck and throw Exception if failed
}
private check3() throws Check3FailedException() {
//DoCheck and throw Exception if failed
}
I would simply rewrite the method with same amount of parameters and return value of DbObject's type.
Don't really understand what are those checks doing(they check if object's atributes are in range of parameters?..), but i would code something like this:
public DbObjectType validate(param1, param2, ...) {
// if one of the checks fail, validation failed
if (check1 || check2 || ...checkN) {
add error;
return null;
}
else {
DbObject obj = getDbObject();
if (lastCheck) {
exception
return null;
}
return obj;
}
}
You don't have to have every if on separate line, if the actions performed after if are the same for every if. Chaining them together makes the code more readable.
As the return value is DbObject, returning null will not break the program because object types can be null.
You could apply the Strategy Pattern.
Define a ValidationStrategy interface that expose the method public abstract void validate()
Define a class ConcreteValidationA that implements the method validate() with the behaviour of your validate(param1, pararm2, param3 ...)
Define a class ConcreteValidationB that implements the method validate() with the behaviour of the alternative method
In the Context class (i.e. the class where your method stays) add a reference to a ValidationStrategy and modify validate(param1, pararm2, param3 ...) to choose a validation strategy and calling the relative validate() method by forwarding.
Context example
class Context {
/*... your methods and members */
public Context(){
//...
strategy=new ConcreteStrategyA(); //defalut strategy
private ValidationStrategy strategy;
public void validate(int param1, int param2,int param3){
if(param1<param2 && param1<param3)
strategy=new ConcreteStrategyA();
else
strategy=new ConcreteStrategyB();
strategy.validate();
}
}

is this java interface tactic sound?

I've been thinking about implementing a certain tactic for my code.
This is my setup:
I've got an interface called "Object".
Then I've got an interface called "Entity" that extends "Object".
From entity then springs countless implementations, like "army", "city", "lemon", etc.
Now, I want to gather all of these Objects into some form of map. Then from that map I want to get the particular implementation of "Object".
My thought out solution for this is as follows:
Object has method :
public Entity getEntity()
All implementations of Object returns null, while Entity returns itself.
Likewise, in entity I'd have:
public Army getArmy()
public City getCity()
That way, I can simply pull an object from the map and get the specific class from it with a series of null checks, like so;
Object o = Objects.getObject(2dCoordinates);
Entity e = o.getEntity();
if (e != null){
Army a = e.getArmy();
if (a != null)
a.armySpecificMethod();
}
All without using "instanceof" and casting, which I hate.
The question is whether there's some unforeseen problem about this? I'd rather learn from someone that knows before refactoring my code and find out for myself.
You asked if there are any pitfalls to your strategy. I would say no, since C# uses the same strategy with their as keyword. Example: e as Army would return e if e is-a Army, or null otherwise. It is basicly a cast that instead of failing returns null.
However you don't have to implement this functionality using interfaces, you can write your own as method for example like this:
static <T> T as(Class<T> clazz, Object obj) {
if (clazz.isInstance(obj)) {
return (T) obj;
}
return null;
}
usage:
Object o = Objects.getObject(2dCoordinates);
Entity e = as(Entity.class, o);
if (e != null) {
Army a = as(Army.class, e);
if (a != null)
a.armySpecificMethod();
}
Another approach would be to register callbacks/strategies to be invoked on particular events. Something like that:
public interface OnMapClicked<T> {
void onItemSelected(T item);
}
And your GameMap (or whatever) implementation would be:
public GameMap {
private final Map<Class<?>, OnMapClicked> listeners = new HashMap<>();
public <T> void registerListener(Class<? extends T> type, OnMapClicked<T> listener) {
listeners.put(type, listener);
}
//
private void onMapClicked(Coordinates coordinates) {
Object object = findObject(coordinates);
listeners.get(object.getClass()).onItemSelected(object);
}
}
That's very rough untested implementation, but hopefully you got the idea. There is one usage of non-generic instance here (in onMapClicked), but it should be safe, since we're checking the input type in registerListener.

Passing Two different Object type to a single Method in Java?

I try to follow this Stackoverflow post but it was not helping my purpose what I wanted to achieve. I want to know is it achievable in Java. Here is the problem statement. I tried to look into Java reflection, Haskel Either, etc. but it endup having two different objects.
I have two type of objects.
com.mobilesecuritycard.openmobileapi.Session msc_session;
org.simalliance.openmobileapi.Session sim_session
I want to have a method which accepts any of the two objects given above.
For example
public void runOperation(Object activeSession) {
activeSession.openLogicalChannel(APPLET_AID);
-- do the rest of operations ---
}
I want to use that function as given below
if(isSetSIMSessionTrue()){
Log.i(LOG_TAG, "Using SIM Session as its True");
sim_session = getSim_session();
runOperation((org.simalliance.openmobileapi.Session) sim_session);
} else{
Log.i(LOG_TAG, "Using MSC Session as its false");
msc_session = getMSCSession();
runOperation((com.mobilesecuritycard.openmobileapi.Session) msc_session);
}
I can even receive correct object class using
String classNameToBeLoaded = activeSession.getClass().getName();
But still not able to get object properties to activeSession object.
Is there any way to pass either of the session object to the runOperation method and only use activeSession for doing rest of the operation. As both objects has same methods and functionality but access different secure element on a android device. So, I do not want to write two different runOperation() method for the different objects. To be more precise, is it possible to cast an object type to another object. I am not sure about this. Any pointers or help will be grateful. I hope, I made my point clear what I want to achieve.
PS: please ignore syntax as I am just providing some code snippets to make my question clear.
You should be able to do this with reflection or even just instanceof, but why? Why not use overloading? Define two methods:
public void runOperation(com.mobilesecuritycard.openmobileapi.Session session) {
}
public void runOperation(org.simalliance.openmobileapi.Session session) {
}
If the goal is to reduce code duplication, then use a single method but have it take the least common ancestor superclass of the two types of sessions, which is hopefully not Object:
public void runOperation(SessionSuperclass session) {
// do something that can work with any type of session
doSomethingMoreSpecific(session);
}
And if necessary, implement two versions of doSomethingMoreSpecific(). That would be the object-oriented way of doing things, not instanceof or reflection.
if(activeSession instanceof com.mobilesecuritycard.openmobileapi.Session) {
// some stuff
} else if(activeSession instanceof org.simalliance.openmobileapi.Session) {
// some other stuff
}
You can do this check in your runOperation().
if(activeSession instanceof org.simalliance.openmobileapi.Session){
// Type 1
}
else if(activeSession instanceof com.mobilesecuritycard.openmobileapi.Session){
// Type 2
}
One solution that springs to mind is to have both of the objects implement a common interface.
For example
public interface ObjectIF
{
public void doSomething();
}
Have some classes that implement the interface:
public class ClassOne implements ObjectIF
{
public void doSomething() { // Code }
}
public class ClassTwo implements ObjectIF
{
public void doSomething() { // Code }
}
Now with your method you can do something like this:
public void doSomethingWithObject(ObjectIF object)
{
// Provided an object implements the interface, it can be passed here.
object.doSomething();
}
is it possible to cast an object type to another object?
Yes, you can cast.
You can check and cast:
if(activeSession instanceof org.simalliance.openmobileapi.Session){
org.simalliance.openmobileapi.Session mySession = (org.simalliance.openmobileapi.Session) activeSession
}
else if(activeSession instanceof com.mobilesecuritycard.openmobileapi.Session) {
com.mobilesecuritycard.openmobileapi.Session mySession = (com.mobilesecuritycard.openmobileapi.Session) activeSession
}

Pass multilevel object method as a parameter

If my method call is:
obj.getLevelOne().getLevelTwo().getValue();
And I want to pass this method as a parameter below:
boolean checkValue( obj, method , value)
{
return obj.method() == value;
}
I want to call the checkValue method like this:
checkValue(obj, "getLevelOne().getLevelTwo().getValue", value);
Is there any way I can accomplish this? Please help.
In java Functions are not a first class concept (yet, coming in Java 8). So it's not possible to pass a method as you can in many other languages that have functional concepts.
What you need to do instead is declare an interface and implement it using an anonymous inner class. e.g.
The Interface
interface MyGetter {
Object doGet();
}
The Check Method
boolean checkValue(MyGetter getter, Object value) {
return getter.doGet().equals(value);
}
The Call
checkValue(new MyGetter() {
public Object doGet() {
return obj.getLevelOne().getLevelTwo().getValue();
}
}, 5);
What we're actually doing in the call is creating a new class and an object of that type to make the actual call you need.
Edit:
If you need different return types you can make the interface and check method generic, e.g.
The Interface
interface MyGetter<T> {
T doGet();
}
The Check Method
<T> boolean checkValue(MyGetter<? extends T> getter, T value) {
return getter.doGet().equals(value);
}
The Call
checkValue(new MyGetter<SomeClass>() {
public SomeClass doGet() {
return obj.getLevelOne().getLevelTwo().getValue();
}
}, 5);
If you really want to do something like this, i recommend either:
1.use a Callable and create anonymous subclasses. NOTE: this is somewhat similar to the approach given above with "MyGetter", except that it uses Callable. There's no need for our own interface, since we can use something that was intended for this purpose that's built into the jdk.
public <T> boolean checkValue(Callable<T> valueGetter, T value) {
return value.equals(valueGetter.call());
}
final MyObject obj = new MyObject();
checkValue(new Callable<String>() {
public String call() { return obj.getLevelOne().getLevelTwo().getValue(); }
}, "foo");
2.using some sort of EL package (mvel works well as an embedded library).
You could then do: "levelOne.levelTwo.value" as your expression, and use mvel to evaluated in on "obj".
public <T> boolean checkValue(Object obj, String expression, T value) {
Object objVal = MVEL.eval(expression, obj);
return value.equals(objVal);
}
checkValue(obj, "levelOne.levelTwo.value", "foo");
Of course, the first one is much more typesafe, though your "expression" would be done at compile time since you're explicitly coding it into the callable implemention. The second approach is more dynamic and lets you compute the expression at runtime.

Design question - java - what is the best way to doing this?

I have a design problem.
I have two data objects which are instances of say class A and class B.
A and B don't have any behavior - they are java beans with getters and setters.
I have a Validation interface and 10 implementations of it defining different Validations.
I would like to specify in my properties file which Validation applies to which class.
Something like this:
class A XYZValidation,ABCValidation
class B: ABCValidation, PPPValidation, etc
How do I write my Validation class so that it serves objects that are instances of Class A OR ClassB, or just about any other Class C that I might want to add in future?
interface Validation {
public boolean check(??);
}
> Just wanted to add this line to say thank you to all those who have responded to this post and to say that I am loving my time here on this amazing website. Stackoverflow rocks!
Have you thought about using annotations to mark the fields you want to validate in your bean?
If you have 10 different validations you could specify 10 annotations. Then mark the fields using annotations:
#ValideStringIsCapitalCase
private String myString;
#ValidateIsNegative
private int myInt;
With reflection API iterate through all the fields and see if they are marked, something like this:
public static <T> validateBean(T myBean) throws IllegalAccessException {
Field[] fields = myBean.getClass().getDeclaredFields();
// This does not take fields of superclass into account
if (fields != null) {
for (Field field : allFields) {
if (field.isAnnotationPresent(ValideStringIsCapitalCase.class)) {
field.setAccessible(true);
Object value = field.get(existingEntity);
// Validate
field.setAccessible(false);
}
}
}
}
An option would be to mark the whole class with the validator you want to use.
EDIT: remember to include annotation:
#Retention(RetentionPolicy.RUNTIME)
for your annotation interface.
EDIT2: please don't modify the fields directly (as in the example above). Instead access their getters and setters using reflection.
I've probably misunderstood the question but would something like this suffice:
public class ValidationMappings {
private Map<Class, Class<Validation>[]> mappings = new HashMap<Class, Class<Validation>[]>();
public ValidationMappings() {
mappings.put(A.class, new Class[]{XYZValidation.class, ABCValidation.class});
mappings.put(B.class, new Class[]{ABCValidation.class, PPPValidation.class});
}
public Class[] getValidators(Class cls) {
if (!mappings.containsKey(cls)) return new Class[]{};
return mappings.get(cls);
}
}
When you want to get the list of validators for a particular class, you would then call getValidators(Class cls) and iterate over each validator and create an instance of each and call your check method.
something like this maybe?
interface Validation {
public boolean check(Validatable x);
}
interface Validatable {
}
class A implements Validatable {
...
}
class Validator {
public boolean validateObject(Validatable x){
boolean validated = true;
... //read config file, check which validation classes to call
//for each validation class v in the config file:
if(!v.check(x)) validated = false;
return validated;
}
}
If you just want it to deal with any object then it'll be Object's that your interface
public boolean check(Object o);
Unless you want to use some marker interface to tag classes that are suitable for validation
Did you mean:
public interface Validation<T> {
boolean check(T object)
}
First of all, I'd use the following interface
interface Validator {
boolean isValid(Object object);
}
to implicitly document what the return value actually means.
Secondly, I'd suggest to document in the interface what behavior is expected if the Validator doesn't know how to handle the given instance.
interface Validator {
/**
* #return false if this validator detects that the given instance is invalid, true if the given object is valid or this Validator can't validate it.
*/
boolean isValid(Object object);
}
That way, you'd simply have a List of Validators that you could throw your objects at.
The performance impact of incompatible Validators should be negligible if they are implemented properly, e.g. with an early instanceof.
On a side note, I'd use a List of Validators instead of a Set so you can order them according to complexity. Put the cheap (performance-wise) Validators at the start of the List as an optimization.
You could then use a general piece of code for validation, e.g.
public class Validators {
public static boolean isValid(Object o, Collection<Validator> validators) {
for(Validator current : validators) {
if(!current.isValid()) return false;
}
return true;
}
}
Depending on your use-case it might be a good idea to return something different than boolean in your interface. If you need information about what is wrong, e.g. to display it, you'd need to return that info instead.
In that case it might be a good idea to keep the above loop running so you'll get all validation errors instead of only the first.
A Visitor pattern would solve this
Calling the Visitor Validator it's possible to have this:
public interface Validatable {
public boolean validate(Validator v);
}
public interface Validator {
public boolean validate(A a);
public boolean validate(B b);
}
public class A implements Validatable {
public boolean validate(Validator v){
return v.validate(this);
}
}
public class B implements Validatable {
public void validate(Validator v) {
return v.validate(this);
}
}
// Default validator just doesn't know how to
// validate neither A's, nor B's
public class GenericValidator implements Validator {
public boolean validate(A a) {
throw new UnsupportedOperationException("Cannot validate A");
}
public boolean validate(B b) {
throw new UnsupportedOperationException("Cannot validate B");
}
}
// since XYZValidation is supposed to run only on A's
// it only overrides A validation
public class XYZValidation extends GenericValidator {
public boolean validate(A a) {
// validate a
return isVAlid(a);
}
}
// since ABCValidation is supposed to run on A's and B's
// it overrides A and B validation
public class ABCValidation extends GenericValidator {
public boolean validate(A a) {
// validate a
return isVAlid(a);
}
public boolean validate(B b) {
// validate b
return isVAlid(b);
}
}
// since ABCValidation is supposed to run only on B's
// it overrides A only B validation
public class PPPValidation extends GenericValidator {
public boolean validate(B b) {
// validate b
return isVAlid(b);
}
}

Categories

Resources