We have an annotation on a function as follows
public class AnInterfaceImpl implements AnInterface {
#FairThreadUsageByEntity(entityName = "XYXYXYX",
numberOfThreads = 1)
public Report getReport(final String One, final String Two) {
//implementation.
}
}
public interface AnInterface {
String BEAN_NAME = "AnInterface"; //used for injection in spring.
Report getReport(final String One, final String two);
}
Spring configuration:
<aop:aspectj-autoproxy />
<bean class="com.amazon.utils.fairthreadusage.aspect.FairThreadUsageByEntityAdvice" />
The annotation is implemented as an aspect. Basic functionality is to limit the number of thread used by a particular type of functionality, let us say download. Below is the code for annotation FairThreadUsageByEntity:
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface FairThreadUsageByEntity {
public String entityName();
public int numberOfThreads();
}
#Aspect
public class FairThreadUsageByEntityAdvice extends FairThreadUsageBase {
#Around("#annotation(fairUsage)")
public Object fairThreadUsageByEntity(final ProceedingJoinPoint pjp, final FairThreadUsageByEntity fairUsage)
throws Throwable {
//Implementation
}
}
The annotation does not work somehow. I am using AspectJWeaver 1.7 and java 1.7.
Let me know if anything else is needed. Any help appreciated.
EDIT: Adding controller as well which call getReport function
public class ReportDownloadRootController extends BaseRootController {
public static final String REQUEST_MAPPING_REPORT_DOWNLOAD = "/hz/inventory/addproducts/status/report";
public static final String PARAM_REFERENCE_ID = "reference_id";
private AnInterface anInterface;
#RequestMapping(REQUEST_MAPPING_REPORT_DOWNLOAD)
public void execute(#RequestParam(value = PARAM_REFERENCE_ID, required = true) final String referenceId,
final HttpServletRequest request, final HttpServletResponse response) {
try {
Report report = AnInterface.getReport(referenceId, getContext().getMerchantId()); //breakpoint here
} catch {
//something
}
}
#Resource(name = AnInterface.BEAN_NAME)
public void setAnInterface(final AnInterface anInterface) {
this.anInterface = anInterface;
}
}
EDIT 2: Spring bean for AnInterface
<bean id="AnInterface" class="com.facade.feed.AnInterfaceImpl" />
I created simple project with all provided by you information and can't reproduce your problem in simple setup, so you have correct implementation of your beans/aspects.
One possible and common error is defining aspect in one context and bean in another, for example aspect is defined in applicationContext and bean is defined in dispatcherServletContext. In such configuration aspect will not work on beans defined in child dispatcherServletContext, only in parent applicationContext
Related
In Payara 5, Jakarta EE 8, I try to inject all the qualified beans and then select a specific one using a qualifier as shown right below:
#Stateless
public class ScheduledTaskExecutor {
#Inject
#Any
private Instance<QCScheduledTask> scheduledTasks;
#Asynchronous
public void executeTask(final String taskName, final String jobID) {
final ScheduledTaskQualifier qualifier = new ScheduledTaskQualifier(taskName);
final QCScheduledTask scheduler = scheduledTasks.select(qualifier).get();
scheduler.execute(jobID);
}
}
public interface QCScheduledTask {
public void execute(final String jobID);
}
The abstract class which extends the interface along with an implementer:
public abstract class AbstractQCScheduledTask implements QCScheduledTask {
private String jobID;
protected abstract void executeTask();
public void execute(final String jobID) {
//
}
protected void updateStatus(final TaskStatus status) {
//
}
}
#Stateless
#QCScheduled(taskName = "TASK_BACKGROUND_JOB_EVALUATION")
public class BackgroundJobEvaluationExecuter extends AbstractQCScheduledTask {
#Inject
private BackgroundJobEvaluator backgroundJobEvaluator;
#Override
protected void executeTask() {
}
}
And the qualifier
#Qualifier
#Retention(RUNTIME)
#Target({METHOD, FIELD, PARAMETER, TYPE})
public #interface QCScheduled {
/**
* Task name discriminator
*
* #return
*/
String taskName();
}
The result is unsatisfied dependencies error.
The same code works on JavaEE 7 application server.
I could not find any difference in the JakartaEE 8 specification, besides, I think that there should not be a restriction on using interfaces and abstract classes together for a runtime resolution of the desired bean implementer.
Annotate the interface QCScheduledTask with #jakarta.ejb.Local
I have a service that uses some object as a generic
#Component
#RequiredArgsConstructor
public class SomeGenericService<T extends Base> {
private final T base;
public void someWork(String info) {
base.someAction(info);
}
}
I also have 3 Base implementations marked with #Component(Base1, Base2, Base3)
I want spring itself to create a service with the generic it needs, for the following example
#Component
#RequiredArgsConstructor
public class Runner implements CommandLineRunner {
private final SomeGenericService<Base1> s1;
private final SomeGenericService<Base2> s2;
private final SomeGenericService<Base3> s3;
#Override
public void run(String... args) throws Exception {
String someString = "text";
s1.someWork(someString);
s2.someWork(someString);
s3.someWork(someString);
}
}
But after the launch, the spring does not understand what I want from it.
Parameter 0 of constructor in SomeGenericService required a single bean, but 3 were found:
- base1: defined in file [Base1.class]
- base2: defined in file [Base2.class]
- base3: defined in file [Base3.class]
Is it possible to set this to automatic, without manually configuring it via the #Bean annotation for each service?
You need to define how those beans should be injected. It's a good practice to have some #Configurations for this purpose. Something like:
#Configuration
#Import({
Base1.class,
Base2.class,
Base3.class
})
public class SomeConfig {
#Bean
SomeGenericService<Base1> someGenericService1() {
return new SomeGenericService(new Base1());
}
#Bean
SomeGenericService<Base2> someGenericService2() {
return new SomeGenericService(new Base2());
}
#Bean
SomeGenericService<Base3> someGenericService3() {
return new SomeGenericService(new Base3());
}
}
I'm interested in using HK2 or Guice for a dependency injection framework.
I know of #Named, #Qualifier, and custom annotations etc. But these are all compile-time.
I am looking for a facility to dynamically determine the desired concrete type based on runtime context and inject the correct implementation.
Is there something like that in HK2 or Guice or a recommended way of achieving this?
For example:
// I would want to turn this...
public final class Handler
{
private final Session session;
#Inject
public Handler(#Named("Database") final Session session)
{
this.session = session;
}
...
}
// into something like this...
public final class Handler
{
private final Session session;
#Inject
public Handler(final Session session)
{
this.session = session;
}
}
// where "session" is injected based on some previous context value ("Database")
// or something to that effect.
I ended up using a feature in HK2 called Operations (link to docs). It allows a user of HK2 to define custom scopes and manage them as "operations". You can find a more detailed example of how to use the feature on HK2's github project: operations example.
This is a simplified example of how I ended up using this feature to inject things based on context or in this case "scope".
Here is some almost-working pseudo-code to demonstrate my usage:
// Create the custom scope annotation.
#Scope
#Proxiable(proxyForSameScope = false)
#Documented
#Target({ ElementType.TYPE, ElementType.METHOD })
#Retention(RetentionPolicy.RUNTIME)
public #interface BatchScope
{
public static final BatchScope INSTANCE = new BatchScopeEnvoy();
}
final class BatchScopeEnvoy extends AnnotationLiteral<BatchScope> implements BatchScope
{
private static final long serialVersionUID = 938233179310254573L;
}
// Create a context used by the HK2 operation feature.
#Singleton
public final class BatchScopeContext extends OperationContext<BatchScope>
{
#Override
public Class<? extends Annotation> getScope()
{
return BatchScope.class;
}
}
// Create a class that holds your custom scope data/context.
public final class BatchScopeRuntime
{
// ... Arbitrary runtime data here ...
public SomeData getData()
{
return this.data;
}
}
// Create a factory that serves up something you want to inject from a custom scope.
#Singleton
public final class DataFactory implements Factory<SomeData>
{
private final OperationManager operations;
#Inject
public BatchInfoFactory(final OperationManager operations)
{
Sentinel.assertIsNotNull(operations);
this.operations = operations;
}
// The #BatchScope on the provide() method indicates that objects returned
// from this factory are in the "BatchScope".
#Override
#BatchScope
public IBatchInfo provide()
{
final OperationHandle handle = this.operations.getCurrentOperation(BatchScope.INSTANCE);
final BatchScopeRuntime runtime = (BatchScopeRuntime)handle.getOperationData();
return runtime.getData();
}
#Override
public void dispose(final IBatchInfo instance)
{
// Do nothing.
}
}
// Setup the injector.
public static ServiceLocator createInjector(final String name)
{
final ServiceLocator injector = ServiceLocatorFactory.getInstance().create(name);
ServiceLocatorUtilities.bind(
injector,
new AbstractBinder()
{
#Override
protected void configure()
{
// This creates a "Singleton" factory that provides
// "SomeData" instances at "BatchScope".
bindFactory(DataFactory.class, Singleton.class)
.to(SomeData.class)
.in(BatchScope.class);
}
}
return injector;
}
// Create a class that needs something in the custom scope.
public final class Foo
{
#Inject
public Foo(final SomeData data)
{
System.out.printf("I got: %s%n", data);
}
}
// Usage: how to manage the scopes using the operations feature.
final SomeData data = ... // get some data
final BatchScopeRuntime runtime = new BatchScopeRuntime(data); // Setup the runtime information.
// Create an operation handle for the custom scope and associate the custom data with it.
final ServiceLocator injector = createInjector("test");
ServiceLocatorUtilities.addClasses(injector, BatchScopeContext.class, Foo.class);
final OperationManager operations = injector.getService(OperationManager.class);
final OperationHandle<BatchScope> batchScope = operations.createAndStartOperation(BatchScope.INSTANCE);
// Operation/scope is now associated with the current thread.
batchScope.setOperationData(runtime);
// Foo will now be injected with: "data" from above.
final Foo foo = injector.getService(Foo.class);
// Do some work...
// Close the operation (make it go out of scope) on the current thread.
batchScope.closeOperation();
I've a little experience in Spring. And I wondering about the amount of callbacks in Spring Context/Bean Lifecycle. I've never used them, and can imaging situations in which the most of them are needed.
My question is: can you provide for each callback at least one example of usage? Means situations when you need that callback.
Conext callbacks:
Bean callbacks:
P.S.:
It is clear for me when majority of callbacks are calling, or what one or another implementation of ApplicationContext was written for. But I can't figure out why someone may want to profit from that callback\implementation. For example:
AbstractRefreshableApplicationContext is using to change bean configurations on fly. But Why? In which situation I may want to change bean's configuration on fly?
afterPropertiesSet callback, obviously is invoked after all bean's properties are setted :) But why I should know about that, and when I should (may want) use it?
can you provide for each callback at least one example of usage?
Look at the javadoc for each of the interfaces, check any of the implementing classes for their purpose and look up their source code for their implementation.
A typical bean definition would be
<bean id="someBean" class="com.example.beans.SomeBean">
<property name="someProperty" value="42" />
<property name="other" value="I will always love you." />
</bean>
with a class like
public class SomeBean {
private String someProperty;
private String other;
public void setSomeProperty(String someProperty) {
this.someProperty = someProperty;
}
public void setOther(String other) {
this.other = other;
}
}
But some times you have classes where you need to perform some logic based on the properties set
public class SomeBean {
private String someProperty;
private String other;
public void setSomeProperty(String someProperty) {
this.someProperty = someProperty;
}
public void setOther(String other) {
this.other = other;
}
public void init() {
Thread thread = new Thread(new Runnable() {
public void run() {
// for example
// send the two property values to some external service
}
});
thread.start();
}
}
This logic can only be performed after the properties have been set. In that case, you can have your class implement the InitializingBean interface (old school)
public class SomeBean implements InitializingBean {
private String someProperty;
private String other;
public void setSomeProperty(String someProperty) {
this.someProperty = someProperty;
}
public void setOther(String other) {
this.other = other;
}
public void init() {
Thread thread = new Thread(new Runnable() {
public void run() {
// for example
// send the two property values to some external service
}
});
thread.start();
}
public void afterPropertiesSet() throws Exception {
init();
}
}
Or annotate it with #PostConstruct (new school)
public class SomeBean implements InitializingBean {
private String someProperty;
private String other;
public void setSomeProperty(String someProperty) {
this.someProperty = someProperty;
}
public void setOther(String other) {
this.other = other;
}
#PostConstruct
public void init() {
Thread thread = new Thread(new Runnable() {
public void run() {
// for example
// send the two property values to some external service
}
});
thread.start();
}
}
This is just an example. The InitializingBean interface is often used along with the FactoryBean interface. It helps to initialize the factory before it produces an object. For more example, see the javadoc of both of those interfaces and look up the source code of the various implementing classes. Do the same for the other *Aware interfaces.
As for AbstractRefreshableApplicationContext, some times you need to refresh() your ApplicationContext. This can happen because you want to reload an XML configuration or because your environment has changed, but you don't want to stop/re-start the application.
1. BeanFactoryPostProcessor:
I give this example as I see this answer: https://stackoverflow.com/a/2349891/4251461
He initially chose BeanFactory for use in integration/performance tests since He didn't want to load the entire application for testing isolated beans. However, He think BeanFactory doesn't support classpath XML configuration. So BeanFactory and ApplicationContext each provide a crucial feature I wanted, but neither did both.
He implements his own ApplicationContext which extends ClassPathXmlApplicationContext.
Here he could use BFPP instead of custom ApplicationContext.
public class LazyInitBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
String[] beanNames = beanFactory.getBeanDefinitionNames();
for (String beanName : beanNames) {
BeanDefinition bd = beanFactory.getBeanDefinition(beanName);
bd.setLazyInit(true);
}
}
}
configure it in spring container like other regular beans:
<bean class="com.example.LazyInitBeanFactoryPostProcessor" />
You can also see the source of PropertyPlaceholderConfigurer and PropertyOverrideConfigurer in spring.
2. InitializingBean:
As Sotirios Delimanolis said: The InitializingBean interface is often used along with the FactoryBean interface. It helps to initialize the factory before it produces an object.
Here is an example.
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import java.security.MessageDigest;
public class SampleDigesterFactory implements FactoryBean<MessageDigest>, InitializingBean {
MessageDigest messageDigest;
String algorithmName = "MD5";
public MessageDigest getObject() throws Exception {
return messageDigest;
}
public Class<?> getObjectType() {
return MessageDigest.class;
}
public boolean isSingleton() {
return true;
}
public void afterPropertiesSet() throws Exception {
messageDigest = MessageDigest.getInstance(algorithmName);
}
public String getAlgorithmName() {
return algorithmName;
}
public void setAlgorithmName(String algorithmName) {
this.algorithmName = algorithmName;
}
}
import java.security.MessageDigest;
public class SampleDigester {
private MessageDigest messageDigest;
public void digestMessage(String message) {
System.out.println("digest message:" + message);
System.out.println("result: " + messageDigest.digest(message.getBytes()));
}
public MessageDigest getMessageDigest() {
return messageDigest;
}
public void setMessageDigest(MessageDigest messageDigest) {
this.messageDigest = messageDigest;
}
}
configure beans in spring container:
<bean id="messageDigesterFactoryMD5" class="com.example.SampleDigesterFactory" />
<bean id="messageDigesterFactorySHA1" class="com.example.SampleDigesterFactory" p:algorithmName="SHA1" />
<bean id="sampleDigesterMD5" class="com.example.SampleDigester" p:messageDigest-ref="messageDigesterFactoryMD5" />
<bean id="sampleDigesterSHA1" class="com.example.SampleDigester" p:messageDigest-ref="messageDigesterFactorySHA1" />
Test it:
SampleDigester sampleDigesterMD5 = context.getBean("sampleDigesterMD5", SampleDigester.class);
SampleDigester sampleDigesterSHA1 = context.getBean("sampleDigesterSHA1", SampleDigester.class);
sampleDigesterMD5.digestMessage("Hello World!");
sampleDigesterSHA1.digestMessage("Hello World!");
The output is:
digest message:Hello World!
result: [B#19d02cb
digest message:Hello World!
result: [B#1753b6d
The spring reference says:
The FactoryBeanconcept and interface is used in a number of places within the Spring Framework;more than 50 implementations of the FactoryBeaninterface ship with Spring itself.
3. BeanPostProcessor:
You can refer to source of RequiredAnnotationBeanPostProcessor in spring.
a BeanPostProcessorimplementation that ships with the Spring distribution which ensures that JavaBean properties on beans that are marked with an (arbitrary) annotation are actually (configured to be) dependency-injected with a value.
When using Spring's based XML configuration, it's easy to decorate multiple implementations of the same interface and specify the order. For instance, a logging service wraps a transactional service which wraps the actual service.
How can I achieve the same using the javax.inject annotations?
You can use #Named together with #Inject to specify which bean to inject.
A simple example with an injected service:
public class ServiceTest {
#Inject
#Named("transactionDecorator")
private Service service;
}
And the corresponding transaction decorator class:
#org.springframework.stereotype.Service("transactionDecorator")
public class ServiceDecoratorTransactionSupport extends ServiceDecorator {
#Inject
#Named("serviceBean")
public ServiceDecoratorTransactionSupport(Service service) {
super(service);
}
}
This exposes your configuration into your code, so I would recommend doing the decorating logic in a #Configuration class and annotate for example the logging service with #Primary. With this approach your test class can look something like this:
public class ServiceTest {
#Inject
private Service service;
And the configuration class:
#Configuration
public class DecoratorConfig {
#Bean
#Primary
public ServiceDecorator serviceDecoratorSecurity() {
return new ServiceDecoratorSecuritySupport(
serviceDecoratorTransactionSupport());
}
#Bean
public ServiceDecorator serviceDecoratorTransactionSupport() {
return new ServiceDecoratorTransactionSupport(serviceBean());
}
#Bean
public Service serviceBean() {
return new ServiceImpl(serviceRepositoryEverythingOkayStub());
}
#Bean
public ServiceRepository serviceRepositoryEverythingOkayStub() {
return new ServiceRepositoryEverythingOkStub();
}
}
My second example doesn't expose any details about which implementation that will be returned, but it depends on several Spring specific classes.
You can also combine the two solutions. For example use Spring's #Primary annotation on a decorator and let Spring inject this decorator into the instance of the given type.
#Service
#Primary
public class ServiceDecoratorSecuritySupport extends ServiceDecorator {
}
This is the sort of thing you typically use AOP for, rather than writing and wrapping implementations manually (not that you can't do that).
For AOP with Guice, you'd want to create a transactional MethodInterceptor and a logging MethodInterceptor, then use bindInterceptor(Matcher, Matcher, MethodInterceptor) to set which types and methods should be intercepted. The first Matcher matches types to intercept, the second matches methods to intercept. Either can be Matchers.any(), match a specific annotation on a type or method (#Transactional, say) or whatever you want. Matching methods are then intercepted and handled automatically. Decorator pattern with a lot less boilerplate, basically.
To do it manually, one way would be:
class ServiceModule extends PrivateModule {
#Override protected void configure() {
bind(Service.class).annotatedWith(Real.class).to(RealService.class);
}
#Provides #Exposed
protected Service provideService(#Real Service service) {
return new LoggingService(new TransactionalService(service));
}
}
#Target(PARAMETER)
#Retention(RUNTIME)
#BindingAnnotation
public #interface Decorate {
Class<?> value();
}
/* see com.google.inject.name.NamedImpl for rest of
the methods DecorateImpl must implement */
public class DecorateImpl implements Decorate, Serializable {
private final Class<?> value;
private DecorateImpl(Class<?> val) {
value = val;
}
public static Decorate get(Class<?> clazz) {
return new DecorateImpl(clazz);
}
public Class<?> value() {
return value;
}
...
...
}
Here is how to use it:
public interface ApService {
String foo(String s);
}
public class ApImpl implements ApService {
private final String name;
#Inject
public ApImpl(#Named("ApImpl.name") String name) {
this.name = name;
}
#Override
public String foo(String s) {
return name + ":" + s;
}
}
First decorator:
public class ApDecorator implements ApService {
private final ApService dcrtd;
private final String name;
#Inject
public ApDecorator(#Decorate(ApDecorator.class) ApService dcrtd,
#Named("ApDecorator.name") String name) {
this.dcrtd = dcrtd;
this.name = name;
}
public String foo(String s) {
return name + ":" + s + ":"+dcrtd.foo(s);
}
}
Second decorator:
public class D2 implements ApService {
private final ApService dcrt;
#Inject
public D2(#Decorate(D2.class) ApService dcrt) {
this.dcrt = dcrt;
}
#Override
public String foo(String s) {
return "D2:" + s + ":" + dcrt.foo(s);
}
}
public class DecoratingTest {
#Test
public void test_decorating_provider() throws Exception {
Injector inj = Guice.createInjector(new DecoratingModule());
ApService mi = inj.getInstance(ApService.class);
assertTrue(mi.foo("z").matches("D2:z:D:z:I:z"));
}
}
The Module:
class DecoratingModule extends AbstractModule {
#Override
protected void configure() {
bindConstant().annotatedWith(Names.named("ApImpl.name")).to("I");
bindConstant().annotatedWith(Names.named("ApDecorator.name")).to("D");
bind(ApService.class).
annotatedWith(DecorateImpl.get(ApDecorator.class)).
to(AnImpl.class);
bind(ApService.class).
annotatedWith(DecorateImpl.get(D2.class)).
to(ApDecorator.class);
bind(ApService.class).to(D2.class);
}
}
If bindings configuration looks ugly, you can create Builder/DSL that looks nice.
The drawback is that (comparing with manual chain building) you can not chain the same module twice (i.e. D2->D2->D1->Impl) and the boilerplate in the constructor params.