User defined Validations coupling issue - java

Have an API defined that clients will be able to utilize. Clients will be connected via a variety of means. One of them is java-to-java. In this specific case, am having an issue. Obviously, the API should be as decoupled from the implementation as possible. I haven't had the chance to test this yet, but won't user defined validations break this model?
I am enabling the Validation via Spring #Validated on the API server-side implementation. Did not want to put this into #Controller class as that is not the only way into the service (API).
For example, if I have this method defined in the Interface:
SomeObject updateOperation( AnInputClass param) ...
I can then annotate with JSR-303 validations and still be de-coupled:
#NonNull
SomeObject updateOperation( #NonNull AnInputClass param) ...
But if I want custom validation on the various pieces/parts of the input "param", I need to make my own Annotation, which has an #Constraint(validatedBy) part This part will tie to the validation implementation. The abbreviated form of this would look like:
SomeObject updateOperation ( #CheckInput AnInputClass param)...
...where the annotation is defined as
...
#Constraint(validatedBy = CheckInputValidator.class) // this is the coupling issue
public #interface CheckInput { ....
Since this all happens server-side, there should be no need to have Java clients have to have this CheckInputValidator class; however, I am seeing no options. First, I like having the validations in the API - they tell users what will be validated. If I could break the dependency and move the validation down to the implementation that would seem like an acceptable tradeoff. However that results in the exception below so it seems like I am stuck. Can anyone help?
javax.validation.ConstraintDeclarationException: Only the root method of an
overridden method in an inheritance hierarchy may be annotated with parameter
constraints, but there are parameter constraints defined at all of the
following overridden methods

Found the answer myself, I should have realized this earlier!
All I needed to do was to use the "#Valid" annotation in the interface/API layer. Then, making sure the #Target annotation on the User Defined / Custom annotation has "TYPE" defined, apply the #CheckInput annotation to the desired class and everything works perfectly!

Related

JAX-RS: JSON deserialization to legacy objects - how to provide helpers/factories to legacy interfaces?

I have a situation while building a stub test server for testing our newly written client for a legacy system, where I would like to deserialize an incoming JSON request body to an object hierarchy provided by a vendor for the same legacy system.
In other words I would like to use the vendors classes instead of building my own.
I've managed to make the Eclipse Microplatform client (running in latest TomEE) come as far as starting to populate the base legacy object but then it fails with not being able to instantiate an interface inside the object which makes sense as there is no metadata for this.
#POST
#Produces({ MediaType.APPLICATION_JSON })
#Consumes({MediaType.APPLICATION_JSON})
public String post(MessageObject messageObject) {
</pre><p><b>Root Cause</b></p><pre>javax.json.bind.JsonbException: interface /vendor interface class/ not instantiable
org.apache.johnzon.jsonb.JohnzonJsonb.fromJson(JohnzonJsonb.java:200)
org.apache.johnzon.jaxrs.jsonb.jaxrs.JsonbJaxrsProvider.readFrom(JsonbJaxrsProvider.java:182)
...
As I do not have the source for these classes, I was thinking of whether the deserializer could be told otherwise (like Providers in Dependency Injection) how to instantiate the interfaces. I have full control over the client.
I am not very familiar with this, so I would appreciate knowing how to get around this or is this a failed cause?
Yes you can bind an implementation for interfaces, see https://johnzon.apache.org/, johnzon.interfaceImplementationMapping part. It can be set in resources.xml in the configurable provider. The class to set is https://github.com/apache/johnzon/blob/master/johnzon-jsonb/src/main/java/org/apache/johnzon/jaxrs/jsonb/jaxrs/JsonbJaxrsProvider.java and the property key is interfaceImplementationMapping, its value is using properties syntax.
Hope it helps

Guice JIT annotated binding [duplicate]

Suppose I have a class that looks like this:
public class MyClass {
#Inject
public MyClass(#Foo("whatever") Bar dependency) {
// ...
}
}
And I wanted to have some custom logic that can see we're injecting an object of type Bar with an annotation of type #Foo("whatever") and construct a corresponding Bar object...something like a Guice Provider, but that gets more context information about the injection site. Does Guice let me do something like that?
What you're describing isn't possible through normal Guice: Providers are intended to be zero-argument pure functions and there's no way to plumb the injection site information into them as you would a flexible callback function.
You can approximate what you want, though, two different ways:
If you know every single possible value of #Foo's parameter, you can make your #Foo a binding annotation and bind it by providing a Annotation-compatible equals and hashCode. This provides the most intuitive experience: You can do anything with your #Foo you can do with any other type, such as using #Foo in constructors or injecting #Foo("value") Provider<Bar> barProvider.
#Override public void configure() {
for (String value : PREDEFINED_VALUES) {
bind(Bar.class)
.annotatedWith(new FooImpl(value))
.toProvider(new BarProvider(value));
}
}
If you want #Foo to work for arbitrary parameters, you'll need to extend Guice with custom injections. This won't work for constructor injection or alongside any other #Inject annotations, but it will allow you to inspect types after Guice injection is finished to augment them as you see fit (e.g. detecting and reacting to #Foo annotations on fields).
See the example in the Guice docs for more information there.
Internally, Guice's core is effectively a Map<Key, Provider>, where a Key represents a pair of a possibly-parameterized type and an optional binding annotation. The former binding annotation trick works because Guice can map your injection request to a Provider all on its own, where the latter skips Guice's map so you can inspect/construct/inject instances all on your own.
If you're willing to skip the annotation part of your solution, you could inject a BarProvider or BarFactory that exposes a forFoo(String) method, which would give you consistent injection without knowing all your String values ahead of time. This would allow you to use assisted injection or AutoFactory to generate your factory (if you want to generate one instance per call), or let you write a straightforward factory yourself for added flexibility.
public class MyClass {
private final Bar dependency;
#Inject
public MyClass(BarProvider barProvider) {
dependency = barProvider.forFoo("whatever");
// ...
}
}

Interface to concrete class conditional instantiation in Spring

I have a Spring based Java application where a lot of classes use the following autowired interface.. they work off this interface at all places.
#Autowired
private IOperatingSystemManager m_operatingSystemManager;
Right now, there is only one implementation of the interface as follows:
#Component
public class WindowsManager implements IOperatingSystemManager
{
// Windows based shenanigans
}
And the application works as expected. Spring is happy. Everybody is happy.
Alright, not everybody...
So, I want to add another concrete implementation of IOperatingSystemManager ..
#Component
public class LinuxManager implements IOperatingSystemManager
{
// Linux based shenanigans
}
What we want is the auto wiring of IOperatingSystemManager conditionally based on a properties file setting. (say.. os=windows.. basically something that is an arbitrary string and cannot be derived from system properties etc. simply because this is a dummy example. the actual managers are not OS related.)
I don't want to change any of the classes who have autowired to the interface and are working off the interface. All I need is for Spring to look at some logic that will dictate the Autowiring of the variables and wire up the right concrete instance for:
#Autowired
IOperatingSystemManager m_operatingSystemManager
at all the gazillion places.
The documentation & web search talk about profiles, condition, bean factory, qualifiers etc.. but we don't want to use Profiles; and Qualifiers seem to be needing changes to all the interface variable annotations.
Factory methods look promising, but being new to Spring, couldn't find a crisp answer.
What is a simple and recommended way to achieve this?
Instead of scanning the WindowsManager class, create one concrete instance that implements the IOperatingSystemManager interface or another one, depending on the your logical conditions.
First, remove the #Component annotation from the WindowsManager class.
Then, create and scan this #Configuration class, which will act as a factory for your beans:
#Configuration
public class OperatingSystemManagerFactory {
#Bean
public IOperatingSystemManager getOperatingSystemManager() {
if ( /* some logic that evaluates to true if windows */ ) {
return new WindowsManager();
} else {
// Linux default option ;)
return new LinuxManager();
}
}
}
With this solution, you shouldn't need to update anyone of your classes that reference the IOperatingSystemManager interface.
I dont know which version of spring you are using but you have options for this
http://www.intertech.com/Blog/spring-4-conditional-bean-configuration/
Here, as you can see, you can create a bean based on a condition that you can decide. It actully gave your example, Windows and Linux :), so i believe thats what you are looking for.
Edit:
If you are using spring-boot, you have some other Conditional annotations
http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-auto-configuration.html#boot-features-condition-annotations

Java annotation returns cryptic class names

I am somewhat new to Java so perhaps I misunderstand the use cases for annotations in java. My issue is the following:
After annotating a method I receive class names such as $Proxy31 when inspecting the annotations on the method. I am curious why I am receiving class names for my annotations that are similar to this, and what I can do to fix this problem.
Method m = this.remoteServiceClass.getMethod(rpcRequest.getMethod().getName());
RequiredPermission a = m.getAnnotation(RequiredPermission.class);
This returns a null annotation even though I know that the method it is looking up has the RequiredPermission annotation implemented.
for(Annotation a : m.getAnnotations())
{
System.out.println(a.getClass().getName());
}
This prints out the $Proxy31 class names.
Given Annotation a, you need to call annotationType(), not getClass() to determine the type of the annotation. An Annotation object is just a proxy that represents that instance of the annotation on that class.
Object o = ...;
Class c = o.getClass();
Annotation[] as = c.getAnnotations();
for (Annotation a : as) {
// prints out the proxy class name
System.out.println(a.getClass().getName());
// prints out the name of the actual annotation
System.out.println(a.annotationType().getName());
}
When you add annotations in the source code, Java actually creates a bunch of interfaces and classes "under the hood" to allow you (or your tools) to ask the program things about the annotations using restrictions. Method annotations create "dyanmic proxies", and accordingly Java creates classes for you, probably with the name Proxy.
If you are interested in this, read on java.lang.reflect.InvocationHandler and its subtype, AnnotationInvocationHandler
That being said, you should not have to worry about what Java actually generates. I suspect you are not using reflection correctly to inspect your annotations from within a Java program.
also.. remember to set this:
#Retention(RetentionPolicy.RUNTIME)
on your annotation so that it lives beyond the compile.

How can I change annotations/Hibernate validation rules at runtime?

If have a Java class with some fields I want to validate using Hibernate Validator.
Now I want my users to be able to configure at runtime which validations take place.
For example:
public class MyPojo {
...
#NotEmpty
String void getMyField() {
...
}
...
}
Let's say I want to remove the NotEmpty check or replace it with Email or CreditCardNumber, how can I do it? Is it even possible? I guess it comes down to changing annotations at runtime...
You can't do it normally.
Here's what I've done to get more dynamic validations working via Hibernate Validator.
Extend the ClassValidator class.
Override the getInvalidVaues(Object myObj) method. First, call super.getInvalidValues(myObj), then add the hook to your customized validation.
Instantiate your custom validator and call getInvalidValues to validate. Any hibernate annotated validations will kick off at this point, and your custom dynamic validations (anything not supported by annotations) will kick off as well.
Example:
public class MyObjectValidator extends ClassValidator<MyObject>
{
public MyObjectValidator()
{
super(MyObject.class);
}
public InvalidValue[] getInvalidValues(MyObject myObj)
{
List<InvalidValue> invalids = new ArrayList<InvalidValue>();
invalids.addAll(Arrays.asList(super.getInvalidValues(myObj)));
// add custom validations here
invalids.addAll(validateDynamicStuff(myObj));
InvalidValue[] results = new InvalidValue[invalids.size()];
return invalids.toArray(results);
}
private List<InvalidValue> validateDynamicStuff(MyObject myObj)
{
// ... whatever validations you want ...
}
}
So your custom validation code can contain logic like "Do this validation, if the user configured it, otherwise do that one", etc. You may or may not be able to leverage the same code that powers the hibernate validations, but either way, what you are doing is more involved that the 'normal' use case for hibernate validator.
Actually it is possible in hibernate validator 4.1. Just read the documentation about programatic constraint creation.
I don't think you'll be able to remove or change the annotation, it's part of the class definition. You can build a new class, which is possible at runtime but a little involved. Hibernate may support programmatic access to the validations and allow you to override the annotation, I don't know the API that well. Hibernate does a bit of runtime class building itself... that might be a good place to learn how to do it if you're interested.

Categories

Resources