How to make an aspect detect a method with multiple annotations - spring-aop

I have a spring application and I want to use aspects to perform some performance logging.
I want to only log methods annotated with #Measured, so I created an annotation as follows :
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface Measured {
boolean logParameters() default true;
boolean logResponse() default true;
boolean measureTime() default true;
}
The aspect is as follows:
#Aspect
#Component
public class MeasuredAspect {
#Pointcut(value = "#annotation(com.waelawada.web.Measured)")
public void isMeasurableEvent(){
}
#Around(value = "isMeasurableEvent() && #annotation(measured)")
public void addEventToMDC(ProceedingJoinPoint joinPoint, Measured measured) throws Throwable{
String methodName = joinPoint.getSignature().getName();
long startTime = System.currentTimeMillis();
joinPoint.proceed(joinPoint.getArgs());
long endTime = System.currentTimeMillis();
if(measured.measureTime()){
MDC.put(methodName,endTime-startTime);
}
}
}
This works just fine for a method like
#Measured
public boolean getUser() {
}
Now I want to annotate a spring mvc controller method that is already annotated with #RequestMapping, but the apsect doesn't seem to detect it.
#Measured
#RequestMapping(value = "/activity", method = GET)
public final String userProfile(#ModelAttribute(USER) User user,
Model model) {
//Do Something
}
How can i make the aspect detect this method? I am using spring aop definded in the context xml file as <aop:aspectj-autoproxy proxy-target-class="false"/>

Related

Hystrix to Resilience4J

I've been working with Hystrix but now I want to change one project from Hystrix to Resilience4J but I don't not how!
My code is as follow:
#FeignClient(name = "customer-service", fallback = CustomerHystrixFallbackFactory.class)
public interface CustomerClient {
#GetMapping(value = "/customers/{id}")
public ResponseEntity<Customer> getCustomer(#PathVariable("id") long id);
}
And my CustomerHystrixFallbackFactory as follow:
#Component
public class CustomerHystrixFallbackFactory implements CustomerClient{
#Override
public ResponseEntity<Customer> getCustomer(long id) {
Customer customer = Customer.builder()
.firstName("none")
.lastName("none")
.email("none")
.photoUrl("none").build();
return ResponseEntity.ok(customer);
}
}
The thing is when customer-service is down, it returns none, but not a 500 Error message.
So, how can I convert what I have to apply Resilience4J?
Thanks in advance!

How can I access HttpContext Header values in Static class

I am programming an ASP.NET Core 5.0 Web API.
I have a CurrentUser class like this. I want to access the header info anywhere in the project by using CurrentUser.Id. How can I do that? (or where can I initialize httpContext variable?)
public class CurrentUser
{
private static HttpContext _context;
private static UserDto _myUserObj;
public static void Initialize(AuthorizationFilterContext context)
{
_context = context.HttpContext;
_myUserObj = context.HttpContext.Request.Headers["User"] as UserDto;
}
public static int Id()
{
return _myUserObj.Id
}
}
I found some solutions. But I think its not best practice solutions. (There must be another and better way..)
MySolutions is that:
I am building a custom Attribute and i am adding it every API Controller like this:
[MyCustomAttribute]
public class UserController : ControllerBase{
//blablabla
}
After this : I am setting my CurrentUser.Initilaze() method in this Attribute like this:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class MyCustomAttribute: Attribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
//fortest
var userObj = context.HttpContext.Request.Headers["User"];//working
var userObj2 = JsonSerializer.Deserialize<UserDto>(userObj, new JsonSerializerOptions()
{
PropertyNameCaseInsensitive = true
});//working
CurrentUser.Initialize(context);//working
var testResult = CurrentUser.Test();//working
}
}
So I can use CurrentUser static class everywhere in N-Layerd project and I am accessing UserId or another variables..
But i am saying again, I think its not best solution. Because I have to add [MyCustomAttribute] to all Controllers. There must be a better solition.

how to create request type scope through annonation in spring mvc?

requirement is that i want request type scope in particular bean Omsdashboard.java .i have to submit the architecture of controller where i want every time request i want new object .so this can be achieve by request scope because controller is by default singleton that why i cant not handle this problem please explain it. thanks for giving your time.
beans class
Omsdashborad.java
#Component
public class OMSDashBoard implements Serializable{
controller class
I am using autowire but they give singleton object but i want another object when project is loaded both method call onload time first call below method then call first method.
#Autowired
private WebApplicationContext context;
private OMSDashBoard omsDashBoard;
public OMSDashBoard getOMSDashBoard() {
System.out.println("##2"+(OMSDashBoard) context.getBean("omsDashBoard"));
return (OMSDashBoard) context.getBean("omsDashBoard");
}
#Autowired(required = false)
public void setOmsDashBoard(#Qualifier("omsDashBoard") OMSDashBoard omsDashBoard) {
this.omsDashBoard = omsDashBoard;
#RequestMapping(value = "/stuck/order/{fromDate}/{toDate}/{requestType}", method = RequestMethod.POST)
public ResponseEntity<OMSDashBoard> getAllStcukOrdersByRequestType(#PathVariable("fromDate") String fromDate,
#PathVariable("toDate") String toDate, #PathVariable("requestType") String orderTypeCd) {
return new ResponseEntity<OMSDashBoard>(omsDashBoard, HttpStatus.OK);
}
#RequestMapping(value = "order/summary/{fromDate}/{toDate}", method = RequestMethod.POST)
public ResponseEntity<OMSDashBoard> getOrderSummaryDetails(#PathVariable("fromDate") String fromDate,
#PathVariable("toDate") String toDate) {
return new ResponseEntity<OMSDashBoard>(omsDashBoard, HttpStatus.OK);
}
step :
use scope(value="request") in omsdashboard.java
step-2
autowired
public AnnotationConfigWebApplicationContext context;
step-3
OMSDashBoard omsDashBoard = (OMSDashBoard) context.getBean(OMSDashBoard.class); in both method to get new object through bean.

Spring AOP by annotation pointcut annotation not retrieve

I'm using Spring AOP for intercept annoted methods by #MyAnnotation. The intercepting is ok. but, unfortunately, i'm not arrive to have my annotation instance.
My Annotation :
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface MyAnnotation {
String[] description();
}
My Configuration Aspect
#Aspect
public class OAuthAspect {
#Pointcut(value = "execution(public * *(..))")
public void anyPublicMethod() {
}
#Pointcut(value = "#annotation(annotation)", argNames = "annotation")
public void anyAnnotationMethod(MyAnnotation annotation) {
}
#Around(value = "anyPublicMethod() && anyAnnotationMethod(annotation)")
public Object authorization(ProceedingJoinPoint pjp, MyAnnotation annotation) throws Throwable {
//annotation is null
}
}
Example pointcut :
#Service
public class ContextService {
#MyAnnotation(description = {"de1", "des2"})
public String getAll() {
}
}
I don't understand why I can't retrieve the instance of the annotation.
if someone have an idea?
pc : edited
For me the class ContextService does not even compile because of a typo in your annotation: String[] descrition(); (note the missing "p") should really be String[] description();, then it compiles and I can also print the annotation instance.

Request Factory GWT editor change isn't persisting related JDO entities

I'm using (and new to) RequestFactory in GWT 2.5, with JDO entities with a one-to-many relationship, on AppEngine datastore. I've just started using the GWT RequestFactoryEditorDriver to display/edit my objects.
The Driver traverses my objects fine, and displays them correctly. However, when I try to edit a value on the "related" objects, the change doesn't get persisted to the datastore.
When I change b.name on my UI and click "save", I notice only A's persist() call is called. B's persist() is never called. How do I make the editorDriver fire on both ARequest as well as BRequest request contexts? (since what I want is for B's InstanceRequest<AProxy,Void> persist() to be called when my edits are to B objects only.)
Also, AFAICT, if I have an editor on BProxy, any object b that is being shown by the editor (and following the Editor Contract) should automatically be "context.edit(b)"ed by the Driver to make it mutable. However, in my case "context" is an ARequest, not a BRequest.
Do I have to make a ValueAwareEditor like mentioned here: GWT Editor framework
and create a fresh BRequest inside the flush() call and fire it, so that changes to B separately persist in a BRequest before the ARequest is fired?
editorDriver.getPaths() gives me:
"bs"
Also, the driver definitely sees the change to B's property, as editorDriver.isChanged() returns true before I fire() the context.
There are no errors on my client-side or server-side logs, and the Annotation Processor runs with no warnings.
Here's how I setup my driver:
editorDriver = GWT.create(Driver.class);
editorDriver.initialize(rf, view.getAEditor());
final ARequest aRequest = rf.ARequest();
final Request<List<AProxy>> aRequest = aRequest.findAByUser(loginInfo.getUserId());
String[] paths = editorDriver.getPaths();
aRequest.with(paths).fire(new Receiver<List<AProxy>>() {
#Override
public void onSuccess(List<AProxy> response) {
AProxy a = response.get(0);
ARequest aRequest2 = rf.aRequest();
editorDriver.edit(a, aRequest2);
aRequest2.persist().using(a);
}
});
This is how my entities look:
public abstract class PersistentEntity {
public Void persist() {
PersistenceManager pm = getPersistenceManager();
try {
pm.makePersistent(this);
} finally {
pm.close();
}
return null;
}
public Void remove() {
PersistenceManager pm = getPersistenceManager();
try {
pm.deletePersistent(this);
} finally {
pm.close();
}
return null;
}
}
#PersistenceCapable(identityType = IdentityType.APPLICATION)
#Version(strategy=VersionStrategy.VERSION_NUMBER, column="VERSION",
extensions={#Extension(vendorName="datanucleus", key="field-name", value="version")})
public class A extends PersistentEntity {
... (Id, version omitted for brevity)
#Persistent
private String name;
#Persistent
private List<B> bs;
public String getName() {
return name;
}
...
public void setName(String name) {
this.name = name;
}
public List<B> getBs() {
return bs;
}
public void setBs(List<B> bs) {
this.bs = bs;
}
}
... (same annotations as above omitted for brevity)
public class B extends PersistentEntity {
... (Id, version omitted for brevity)
#Persistent
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Here are the proxies:
#ProxyFor(A.class)
public interface AProxy extends EntityProxy {
String getName();
List<BProxy> getBs();
void setName(String name);
void setBs(List<BProxy> bs);
}
#ProxyFor(B.class)
public interface BProxy extends EntityProxy {
String getName();
void setName(String name);
}
Here are my service stubs:
#Service(A.class)
public interface ARequest extends RequestContext {
Request<List<A>> findAByUser(String userId);
InstanceRequest<AProxy, Void> persist();
InstanceRequest<AProxy, Void> remove();
}
#Service(B.class)
public interface BRequest extends RequestContext {
Request<List<A>> findB(String key);
InstanceRequest<BProxy, Void> persist();
InstanceRequest<BProxy, Void> remove();
}
Edit:
I've now changed my ARequest interface and service implementation to support a "saveAndReturn" method, so that I can recursively "persist" "a" on the server side:
Request<UserSandboxProxy> saveAndReturn(AProxy aProxy);
I find now that when I "flush" my RequestFactoryEditorDriver, the client-side context object has my new "b.name" value. However, if I call "context.fire()" and inspect my "saveAndReturn" method on the server side, the resulting server-side object "a", just before I "persist" it, doesn't contain the change to "b.name" on any item of the List.
Why could this be happening? How do I debug why this client-information doesn't go across the wire, to the server?
Options I've considered, tried and ruled out:
1) Ensuring the APT has been run, and there are no warnings/errors on Proxy or Service interfaces
2) Ensuring that my proxies does have a valid setter in AProxy for the List
You have to use a session-per-request pattern for RequestFactory to work properly. More details here: https://code.google.com/p/google-web-toolkit/issues/detail?id=7827

Resources