Capture setters inside mapper method using AspectJ in Spring - java

I have java classes like this :
#Data
public class Lead {
private A a;
...
}
#Data
public class A {
private B b;
private String c;
private List<Integer> d;
}
#Data
public class B {
private String e;
private String f;
}
I have a mapper method with annotation like this :
#FieldPermissionAnnotation("a")
public A fetchA(//Some DB Entities) {
A a = new A();
...
a.setB(fetchB());
...
a.setC(fetchC());
...
a.setD(fetchD());
}
My FieldPermissionAspect fetches the permission-field mapping from db for a user and sets field to null if user does not have permission for given field.
I get a list of string field hierarchy like this :
["a-b-e", "a-b-f", "a-c", "a-d"]
I want to set b, c, d to null using #Around around their respective setters inside the fetchA() method.
Is it feasible using AspectJ and spring?
How do I access the setters for b, c, d inside the fetchA() method?

I want to set b, c, d to null using #Around around their respective setters inside the fetchA() method. Is it feasible using AspectJ and spring? How do I access the setters for b, c, d inside the fetchA() method?
As I said in my comment, your question is unclear and I have to guess what you want to do because there is no aspect code. My assumption is that you want to intercept setter methods if (and only if) they are being called from inside a certain other method. I.e. you need a control-flow-dependent pointcut like cflow() or cflowbelow(). According to the Spring manual these pointcuts are not supported by Spring AOP, but you can configure Spring to use full AspectJ with LTW (load-time weaving) instead.
For more details I suggest you show me yours (MCVE, ideally on GitHub with Maven build), then I show you mine (concrete solution).

Related

How can I make fields in Object as required or do field validation?

Let's assume I have a class created by using jsonschemapojo2 as so
public class a{
private String b;
public void setB(String b){this.b = b}
public void getB(){return b}
}
I used this class to parse a result from mongodb into an object:
a = {b : "1"}
The new requirement I have for my application is that an exception must be thrown when the field b is null, empty string or it's not present in the object. I can't use annotations at the class level as the class is created from the jsonschemapojo2. Is there any way to specify the required field annotation at the schema level?. Otherwise how would I create a proxy method that validates the object? should I use reflection or is there a smarter way to do it in springboot?
Yes, bean validation allows to define the constraints in xml file. You can find many examples at Hibernate website.
You can use either one from bellow options to define the constraints -
i) By the programmatic API More Details
ii) By XML : More details
You can’t enable or disable constraints therefore you would have to redefine the metadata at every runtime, which is not a good idea.

POJO breaks Dependency Injection

Independently of the DI Framework used - a single POJO within the object chain always breaks the DI mechanism.
Pseudocode example:
class A {
#Inject
private B b;
}
class B {
private C c=new C();
}
class C {
#Inject
private D d;
}
The injection in class C won't work, as the new C() in class B breaks the chain of managed objects.
We are currently trying to improve our old (non-DI) project by incrementally replacing manual object creation with DI mechanisms.
So how to migrate C to DI, without even caring about A and B?
You can not do that with keeping the direct calls to the constructor (without bytecode manipulation).
Here is a way to semi-automatically refactor your code to what you might need.
The usual IDE lets you create/refactory factory methods out of constructors. With doing that refactoring all calls to new C() will be transformed to C.createInstance() (or whatever the factory method is called).
Afterwards change the factory method to actually resolve the C from your dependency injection framework.
Normally if you don't want to inject the C you call your container to resolve C:
C c = container.resolve(C.class);
or you let the C also be injected e.g. when calling the constructor
or like you did before:
#Inject
private C c;
Here are is some example code for CDI:
https://jaxenter.de/cdi-geht-fremd-dependency-injection-fur-javase-5039
The resolve the needed object by using:
UpdateCustomerController controller = (Controller) BeanProvider.getContextualReference("updateController", false);

Java type level annotation and private member visibility

I'm trying to externalize the baseurl of a spring #Controller into a static String member of the controller class. If i do so i have to declare the member public - otherwise it will not be visible to the #RequestMapping annotation. I can't understand why - isn't the annotation part of the class?
Can someone explain why i am forced not to use private here?
Invalid:
#Controller
#RequestMapping(PendingApprovalsController.CONTROLLER_URL)
public class PendingApprovalsController {
private static final String CONTROLLER_URL = "/some/url";
...
}
Valid:
#Controller
#RequestMapping(PendingApprovalsController.CONTROLLER_URL)
public class PendingApprovalsController {
public static final String CONTROLLER_URL = "/some/url";
...
}
An annotation is an ordinary Java class itself. It can't see the members of an annotated class unless they are visible to it, using normal Java rules. Furthermore the existence of annotations may be used by other code at runtime to operate on the members of the annotated class; if those members are not visible, those operations can't be performed.
This page from the JDK documentation package talks about how to define custom annotations, and how to consume annotations applied in code, and it's enlightening in this regard. To define an annotation type, you do something like
public #interface Copyright {
String value();
}
Your custom annotation is defined as a special kind of Java interface; in user, the JVM supplies a runtime implementation as needed. But the key thing to note is how you use your custom annotation, for example:
Method m = ... // Get a java.lang.reflect.Method object from somewhere
if (m.hasAnnotation(Copyright.class)) ...
Note that here we refer to the class object of the annotation type, demonstrating that an annotation is compiled to a normal Java type.

Java Extending an Object Except for Some Attributes of Parents

I have a class C extends B. and B extends A. A has an attribute name. I don't want to see name attribute at C class.
How can I do that ignore?
PS: If it is not possible at Java: I am working on a Spring project that uses Apache CXF and has a web service capability. I want to get B type object from client and send C type object to client. Because of my design issues I don't want to change my inheritance mechanism. If there is a way can I ignore name field at C class? I am implementing as first-code style.
You can declare name field in A as private and keep both A and B in same Package.
package A;
Class A {
protected String name;
}
Class B extends A{
// B can access A's attribute
}
package C;
Class C extends B{
// C cannot access name attribute defined in A.
}
And keep C is in a different package.
Please read about composition over inheritance. If you need to hide some elements then probably you do not understood properly the Object Oriented code design.
The example provided by you is too narrow to create any better answer. But what is the point of hiding in C when, you can cast it to A and still use it ?
I have a class C extends B. and B extends A. A has an attribute
name. I don't want to see name attribute at C class.
Based on your edit, you are trying to hide an attribute from a superclass (A) in the serialized representation of one of it's subclasses (C). Assuming you are using JAX-WS/JAX-RS, you can do this by overriding the property in the subclass and applying annotations to mark it as not eligible for serialization. The primary annotation to apply will be the JAXB annotation #XmlTransient. You can also #JsonIgnore the property, if you are providing the option to serialize objects as JSON. Pseudo code shown below:
#XmlRootElement
public class A implements Serializable {
private String name;
// ...
}
#XmlRootElement
public class C extends A {
#Override
#XmlTransient
public String getName() {
return super.getName();
}
}

How can I access private class members in Java?

I have data model classes that contain private fields which are meant to be read-only (via a getter function). These fields are set by my JPA persistence provider (eclipselink) during normal operation, using the contents of the database. For unit tests, I want to set them to fake values from a mockup of the persistence layer. How can I do that? How does eclipselink set these values, anyway?
Simplified example:
#Entity
class MyEntity
{
#Id
private Integer _ix;
public Integer ixGet()
{
return this._ix;
}
}
Can you just Mock the Entity itself, providing your own implemenations of the getters?
You could create an anonymous extension in your mock persistence layer:
MyEntity x = new MyEntity() {
public Integer ixGet() { return new Integer(88); }
};
You need to use the Reflection API. Use Class.getField() to get the field, then call setAccessable(true) on that field so that you may write to it, even though it is private, and finally you may call set() on it to write a new value.
For example:
public class A {
private int i;
}
You want to set the field 'i' to 3, even though it is private:
void forceSetInt(Object o, String fieldName, int value) {
Class<?> clazz = o.getClass();
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(o, value);
}
There are a number of exceptions that you will need to handle.
You can use a test library like Mockito to access objects internal state in read and write mode. For example with Mockito use:
//read
Integer i = Whitebox.getInternalState(myEntity,"_ix")
//Write
Whitebox.setInternalState(myEntity,"_ix", 123)
You can use a mocking framework like powermock to by pass encapsulation. In powermock you'd use Whitebox.setInternalState(..) to set a private member.
A less invasive method would be to mock the getter method. Whether this is feasible would depend on what else depends on the internal state but if it is enough, it's the cleaner solution.
Some methods I've used in the past:
Make _ix protected, create a subclass where you implement a setter
Make a constructor taking the value for _ix as a parameter
Use reflection
Another option, if you really hate to make things public, is to create a subclass for testing, and provide public access there.
You have a few options:
Create stubs to replace your entity (extract an interface first)
Use Reflection
Add a public setter for testing
Keep your tests within the package and use a default scope
For a bunch of useful techniques, have a look at Michael Feather's book, Working Effectively With Legacy Code
You can add constructor with parameter for your read-only variable. Don't forget to add a default (zero parameter) constructor.
#Entity
class MyEntity
{
#Id
private Integer _ix;
public MyEntity(Integer ix) {
_ix = ix;
}
public MyEntity() {
/*
* Default constructor
*/
}
public Integer ixGet()
{
return this._ix;
}
}
The constructor is a best way I think. If this entity has to be really readonly (not allowed to create new instances in production code at all) you can make constructor with package access and use it only within the tests. And there is a possibility that even if you make your default constructor private or with package access, your persistance provider still be able to work with such entity, but not sure though - check with eclipselink docs.

Categories