I'm trying to understand how this annotation is invoked #WebMethod
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
#WebService //<----- is this annotation nested in WebService class
#SOAPBinding(style = Style.RPC)
public interface TimeServer {
#WebMethod String getTimeAsString(); //<-------is this nested in a class too
#WebMethod long getTimeAsElapsed();
}
According to my import javax.jws.WebMethod, and to Java docs
http://docs.oracle.com/javase/7/docs/api/javax/jws/WebMethod.html
public #interface WebMethod is described.
Is the #WebMethod annotation defined as the WebMethod class?
Could the source code for the WebMethod class be something like this?
Public class WebMethod{
//members
//methods
public #interface WebMethod{ //annotation definition in class, is this possible
}
}
If this is not the case, please let me how it's done with a simple example.
No, like it says in the Javadoc you linked to, this is defined as
#Retention(value=RUNTIME)
#Target(value=METHOD)
public #interface WebMethod
So this is an annotation (#interface) that you put on a method (#Target(value=METHOD)).
#WebMethod is not "nested" into #WebService, those are two independent annotations (but of course, they work in concert). That one goes on a method and the other on a class is defined by the #Target.
While that does not seems to be the case in this specific instance I ran across the same question of whether inner annotations where ok.
According to my experiments this works
Annotation definition:
// pkg2/I.java
package pkg2;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Retention;
public final class I {
private I(){
}
#Retention(RetentionPolicy.RUNTIME)
public static #interface Inner {}
}
Usage:
// pkg/C.java
package pkg;
import pkg2.I;
#I.Inner
public class C {
public static void main(String[] args) throws Exception {
System.out.println(C.class.getAnnotation(I.Inner.class));
}
}
Running:
$ java pkg/C
#pkg2.I$Inner()
Related
I am still a beginner in Spring Framework so I tried to code a program about "introduction" in Spring AOP but I am facing an error while compiling. Please find below the classes in the package concert:
PerformanceImp.java
package concert;
import org.springframework.stereotype.Component;
#Component
public class PerformanceImp implements Performance {
public void perform() {
System.out.println("This is the performance function");
}
}
Performance.java
package concert;
public interface Performance {
public void perform();
}
Encoreable.java
package concert;
public interface Encoreable {
void performEncore();
}
DefaultEncoreable.java
package concert;
import org.springframework.stereotype.Component;
#Component
public class DefaultEncoreable implements Encoreable {
public void performEncore() {
System.out.println("This is the performEncore function");
}
}
EncoreableIntroducer.java
package concert;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;
import org.springframework.stereotype.Component;
#Component
#Aspect
public class EncoreableIntroducer {
#DeclareParents(value="concert.Performance+",
defaultImpl=DefaultEncoreable.class)
public static Encoreable encoreable;
}
ConcertConfig.java
package concert;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
#Configuration
#EnableAspectJAutoProxy
#ComponentScan("concert")
public class ConcertConfig {
}
And the main class:
Main.java
package concert;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(ConcertConfig.class);
PerformanceImp pi = (PerformanceImp) context.getBean(PerformanceImp.class);
((Encoreable) pi).performEncore();
pi.perform();
}
}
I am getting the error:
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'concert.PerformanceImp' available
Any help please ?
You cannot access the implementation (PerformanceImp) by default, because you enabled AOP, which sets to target interfaces instead of implementation. If you would remove EnableAspectJAutoProxy, you would see the code would work fine.
To understand a bit more about how AOP targeting works, take a look at this Spring Documentation
Spring AOP can also use CGLIB proxies. This is necessary to proxy
classes rather than interfaces. CGLIB is used by default if a business
object does not implement an interface. As it is good practice to
program to interfaces rather than classes; business classes normally
will implement one or more business interfaces. It is possible to
force the use of CGLIB, in those (hopefully rare) cases where you need
to advise a method that is not declared on an interface, or where you
need to pass a proxied object to a method as a concrete type.
So you have two options:
Take the interface when trying to get the bean from the ApplicationContext.
Enable AOP to target concrete classes instead.
To do this point #2, modify your annotation as follows:
#EnableAspectJAutoProxy(proxyTargetClass = true)
Try:
Performance pi = context.getBean("performanceImp", Performance.class);
instead of:
PerformanceImp pi = (PerformanceImp) context.getBean(PerformanceImp.class);
I have an abstract class (database mapping) implementing an interface where default implementations are injected at runtime (this is part of another library and cannot be changed).
I want to override one of the default implementation via a proxy (as that seems like the way to override this).
public abstract class Table1 implements Storable<Table1>
{
#Sequence("ID_SEQUENCE")
#Alias("ID")
public abstract String getID();
public abstract void setID(String ID);
#Alias("NAME")
public abstract String getAvailabilityZone();
public abstract void setAvailabilityZone(String value);
}
public interface Storable<S extends Storable<S>> {
//a bunch of method definition.
boolean tryLoad() throws Exception;
}
Let's say I want to override tryLoad() method to do my own things instead of what the generated code provides. Given the nature of the library, it is not something I can achieve by simple #Override.
The simple way this is currently used is as following:
public void method() {
Table1 t = Repository.storageFor(Table1.class).prepare();
t.setName( "temp" );
if (!t.tryLoad())
t.tryInsert();
}
I want to proxy tryLoad() without making changes in all the methods across the whole codebase - that would be to get proxied instance instead of actual one and perform the operation on that.
Is there any recommended way to achieve this?
Thanks!
I woke up last night and felt bored, so despite your lack of feedback I created a little Carbonado showcase project and shared it on GitHub. I made three commits:
Initial commit with Maven project already prepared for AspectJ and a JUnit test for me to find out how Carbonado actually works, because I had never used it before.
Add failing unit test for behaviour of tryLoad() expected to be provided by aspect.
Add aspect to make unit test pass. Aspect hooks into tryLoad() and auto-creates non-existent record. I do not know if I guessed right what you actually wanted to achieve, but if it was a different thing, just change the aspect implementation.
Sample code
Carbonado storable:
package de.scrum_master.app;
import com.amazon.carbonado.Nullable;
import com.amazon.carbonado.PrimaryKey;
import com.amazon.carbonado.Storable;
#PrimaryKey("ID")
public interface StoredMessage extends Storable<StoredMessage> {
long getID();
void setID(long id);
#Nullable String getMessage();
void setMessage(String message);
}
Aspect:
package de.scrum_master.aspect;
import com.amazon.carbonado.Storable;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
#Aspect
public class CarbonadoAspect {
#Around("call(boolean tryLoad()) && target(storable)")
public boolean tryInsertIfNotFound(ProceedingJoinPoint thisJoinPoint, Storable storable) throws Throwable {
System.out.println(thisJoinPoint);
if ((boolean) thisJoinPoint.proceed())
return true;
System.out.println("Not found: " + storable + " -> inserting");
return storable.tryInsert();
}
}
JUnit test:
package de.scrum_master.app;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.amazon.carbonado.FetchException;
import com.amazon.carbonado.PersistException;
import com.amazon.carbonado.Repository;
import com.amazon.carbonado.RepositoryException;
import com.amazon.carbonado.Storage;
import com.amazon.carbonado.SupportException;
import com.amazon.carbonado.repo.map.MapRepositoryBuilder;
import de.scrum_master.app.StoredMessage;
public class CarbonadoTest {
private Repository repo;
private Storage<StoredMessage> storage;
StoredMessage message;
#Before
public void setUp() throws Exception {
repo = MapRepositoryBuilder.newRepository();
storage = repo.storageFor(StoredMessage.class);
message = storage.prepare();
}
#After
public void tearDown() throws Exception {
repo.close();
repo = null;
storage = null;
message = null;
}
// (...)
#Test
public void aspectCreatesNonExistentRecord() throws SupportException, RepositoryException {
message.setID(1);
// Without the aspect this would be false
assertTrue(message.tryLoad());
assertEquals(message.getID(), 1);
assertEquals(message.getMessage(), null);
}
}
Enjoy!
I'm developing an SDK, which will be used to create additional applications for batch processing. There is core-a-api module, which holds interface Client
public interface Client {
void send();
}
and core-a-impl which holds couple implementations for Client interface - HttpClient and TcpClient.
Also, there is one more core module core-b-impl, which uses a particular instance of Client interface.
public class SendingTasklet implements Tasklet {
#Autowired
private Client client
public void process() {
client.send();
}
}
What instance should be created (HttpClient or SftpClient) should be decided by the user, who creates an application using SDK. He also needs to have an ability to create its own implementation for Client and use it in SendingTasklet. A user from core dependencies can see only interfaces from -api modules. For dependency injection, I'm using Spring. All beans for particular modules are created in each module separately. The user created beans are created in user's configuration class
#Configuration
public class UsersApplicationConf {
#Bean
public Client client {
return new UsersClient();
}
}
The issue is, that somehow without exposing -impl module details for user application, he should be able to decide what Client implementation can be used from the core provided implementations or he should be able to pass one of its own.
The first thought was to use qualifiers when injecting into SendingTasklet, but then you need to create a separate instance variable for each implementation in SendingTasklet and this is not very good because if there would be more implementations for Client interface it would be required to change SendingTasklet as well. And also the problem, that user should somehow decide wich implementation to use persists.
What I did, I exposed core-a-impl for client's application. So in his configuration, he can decide what instance to create for Client interface.
#Configuration
public class UsersApplicationConf {
#Bean
public Client client {
return new HttpClient();
}
}
But this is not very smart as well and I'm thinking is there any other way how to solve this issue?
You can use strategy or factory pattern as mentioned here but personally I would go with JSR 330 that you can find an example here , below code block for spring example:
package spring;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import static spring.Spring.Platform;
#Configuration
#ComponentScan
public class Spring {
public static void main(String[] args) {
new AnnotationConfigApplicationContext(Spring.class);
}
#Autowired
#Platform(Platform.OperatingSystems.ANDROID)
private MarketPlace android;
#Autowired
#Platform(Platform.OperatingSystems.IOS)
private MarketPlace ios;
#PostConstruct
public void qualifyTheTweets() {
System.out.println("ios:" + this.ios);
System.out.println("android:" + this.android);
}
// the type has to be public!
#Target({ElementType.FIELD,
ElementType.METHOD,
ElementType.TYPE,
ElementType.PARAMETER})
#Retention(RetentionPolicy.RUNTIME)
#Qualifier
public static #interface Platform {
OperatingSystems value();
public static enum OperatingSystems {
IOS,
ANDROID
}
}
}
interface MarketPlace {
}
#Component
#Platform(Platform.OperatingSystems.IOS)
class AppleMarketPlace implements MarketPlace {
#Override
public String toString() {
return "apple";
}
}
#Component
#Platform(Platform.OperatingSystems.ANDROID)
class GoogleMarketPlace implements MarketPlace {
#Override
public String toString() {
return "android";
}
}
Edit: I didnt test the code but I have used javax.inject.Qualifier
with CDI if this code doesnt work let me know I will update with
correct combination and imports
In an aspect, i'd like stop at a specified method. This method has one parameter which is annotated with a class level annotation:
The annotation is:
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
public #interface Auditable {}
The parameter is an object of a class annotated like:
#Auditable
public class User {}
The method I like to inspect:
public Object findSingleResultByExample(final Object entity) {}
This aspect is not working:
#AfterReturning(value="execution(* org.wtp.repository.GenericDao.find*(#org.wtp.aspects.Auditable (*)))",
argNames = "joinPoint, result",
returning = "result")
private void auditFindAnnotation(final JoinPoint joinPoint, final Object result) {}
First of all, your advice method must be public, not private. Please change that into
public void auditFindAnnotation(...)
It is not working because your pointcut intercepts methods with an #Auditable parameter annotation. Your sample method does not have such an annotation, though. It would work if the method signature was like this:
public Object findSingleResultByExample(final #Auditable Object entity) {}
BTW, then the #Target(ElementType.TYPE) restriction must be removed or extended in order for the code to still compile.
But I guess what you want is not to match on parameter annotations, but on type annotations. Then your pointcut would look like this (no parentheses around * this time):
execution(* org.wtp.repository.GenericDao.find*(#org.wtp.aspects.Auditable *))
But again, this does not match your sample method because its parameter type is not User or Auditable but just Object and the latter does not carry the annotation. You can see the difference if you overload your find* method and do something like this:
package de.scrum_master.app;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
#Retention(RetentionPolicy.RUNTIME)
public #interface Auditable {}
package de.scrum_master.app;
#Auditable
public class User {}
package de.scrum_master.app;
import java.util.ArrayList;
public class Application {
public Object findSingleResultByExample(final Object entity) {
return entity;
}
public Object findSingleResultByExample(final User entity) {
return entity;
}
public static void main(String[] args) {
Application application = new Application();
application.findSingleResultByExample("foo");
application.findSingleResultByExample(new User());
application.findSingleResultByExample(new ArrayList<String>());
}
}
package de.scrum_master.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
#Aspect
public class AuditAspect {
#AfterReturning(
value = "execution(* de.scrum_master.app..find*(#de.scrum_master.app.Auditable *))",
argNames = "thisJoinPoint, result",
returning = "result"
)
public void auditFindAnnotation(final JoinPoint thisJoinPoint, final Object result) {
System.out.println(thisJoinPoint + " -> " + result);
}
}
The console log then looks like this:
execution(Object de.scrum_master.app.Application.findSingleResultByExample(User)) -> de.scrum_master.app.User#4a574795
Update: In order to get the whole thing working without changing or overloading any method signatures, you would have to make your pointcut match all calls and dynamically determine the type and its annotations from withing the aspect via reflection (not so nice, but possible). Feel free to ask questions if you do not understand this idea.
I have tried many combinations but I am unable to invoke callback before execution of following method
#SomeAnnotation(...)
#Override
public void someMethod(Serializable id) {
}
I have tried many combinations similar to
#Before("execution(#com.full.name.of.SomeAnnotation * com.full.name.of.Class.someMethod(java.io.Serializable))")
public void beforeMethod() {
System.out.println("I am here.");
}
If I write a more generic expession, it hits the beforeMethod but I am unable to target a single specific method. What am I missing here?
Okay guys, let me prove that the pointcut actually works as written by the original poster Haris Hasan.
Sample annotation:
package com.full.name.of;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
#Retention(RetentionPolicy.RUNTIME)
public #interface SomeAnnotation {
int id();
String name();
}
Sample class using the annotation:
package com.full.name.of;
import java.io.Serializable;
public class Class {
#SomeAnnotation(id = 1, name = "John Doe")
public void someMethod(Serializable s) {}
public static void main(String[] args) {
new Class().someMethod("x");
}
}
Sample aspect with Haris Hasan's exact pointcut:
package de.scrum_master.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
#Aspect
public class SampleAspect {
#Before("execution(#com.full.name.of.SomeAnnotation * com.full.name.of.Class.someMethod(java.io.Serializable))")
public void yetAnotherPointcut(JoinPoint thisJoinPoint) {
System.out.println(thisJoinPoint);
}
}
Console output:
execution(void com.full.name.of.Class.someMethod(Serializable))
Copy and paste everything exactly as is, then run it. Quod erat demonstrandum.
The expression below should work:
#Before("com.full.name.of.Class.someMethod(..) && args(java.io.Serializable)")
Correction by kriegaex:
#Before("execution(* com.full.name.of.Class.someMethod(*)) && args(java.io.Serializable)")
A few points worth considering: Is the method being advised public? Are you using cglib proxies or jdk proxies? Does your class implement any interface and is the method being advised declared in the interface contract?
Also do take a look at what spring doc has to say about writing good pointcuts
Hope this helps.
Why do you not just use
#Before("execution(* com.full.name.of.Class.someMethod(java.io.Serializable))")
That specifically targets the method you want, you do not need to put the annotation to specify the target