Spring's Autowired and InitializingBean - spring

I currently employ the following "pattern" on all my Spring component/configuration/service classes:
#Component
final class SomeComponent implements InitializingBean {
private SomeBean someBean;
#Autowired
public SomeComponent(SomeBean someBean) {
this.someBean = someBean;
}
#Override
public void afterPropertiesSet() throws Exception {
Assert.state(someBean != null, "SomeBean should not be null.");
}
public void someMethod() {
someBean.doSomething();
}
}
Should I really be implementing things like this or if I am just adding up to initialization time by making pointless assertions? Does Spring make any guarantees about the nullity of injected beans?

The documentation says:
By default, the autowiring fails whenever zero candidate beans are available; the default behavior is to treat annotated methods, constructors, and fields as indicating required dependencies.
So yes, you're making pointless assertions. BTW, you could do these assertions in the constructor directly, or at least in a #PostConstruct-annotated method, instead of having to override InitializingBean.

Related

How to test a spring component with multiple dependencies?

Trying to write some junits for a component. The issue im having is that that component has an autowired dependency, which itself has 3 autowired dependencies. So when I try to test a method, I keep getting a npe.
#Component
public class Transformer {
private CacheService cacheService;
public Transformer(CacheService cacheService) {
this.cacheService = cacheService;
}
public void doAction(CustomObject o){
cacheService.perform(o);
}
#Component
public class CacheService {
#Autowired private GenericBean genericBean;
#Autowired private Dao dao
public void doAction(CustomObject o){
dao.fetch(o);
}
}
Once it gets to that doAction method i get a npe since all those autowired beans are null. How do I get past this issue? I've tried a few past solutions I saw here, but none worked.
Consider using constructor level injection instead of field level injection (#Autowired on fields). Then you can construct your CacheService with needed mocks. this is best practice in most cases.
Otherwise check Spring #InjectMocks annotation.

Quarkus encapsulation behavior

I have this class:
#ApplicationScoped
public class BookService {
public boolean doorClosed;
public boolean isDoorClosed() {
return doorClosed;
}
}
And I have this test class:
#QuarkusTest
public class BookServiceTest {
#Inject BookService bookService;
#Test
public void testBookServiceDoor() throws InterruptedException {
bookService.doorClosed=true;
assertTrue(bookService.doorClosed);
assertTrue(bookService.isDoorClosed());
}
}
I am surprised that the last test assertion fails. The first passes but the last fails. It almost seems like that the getter/setters are using different variables than the one I am accessing directly.
I did the same test with Spring Boot and got the two assertions passing:
#Service
public class BookService {
public boolean doorClosed;
public boolean isDoorClosed() {
return doorClosed;
}
}
And the test:
#SpringBootTest
public class BookServiceTest {
#Autowired BookService bookService;
#Test
public void testBookServiceDoor() throws InterruptedException {
bookService.doorClosed=true;
assertTrue(bookService.doorClosed);
assertTrue(bookService.isDoorClosed());
}
}
Using the #ApplicationScoped annotation makes the class a normal scoped bean. This means that the container never injects an actual instance of the class; instead, you get a proxy that will lookup the correct instance on each method invocation.
This is most commonly useful for example with #RequestScoped beans, where you get a single proxy, which will dispatch method invocations to instances that belong to the "current request" (typically an HTTP request). However, there are good reasons why you might want this for application scoped beans as well (e.g. when you want lazy initialization).
The rule is: never access fields directly on normal scoped beans, only call methods.
If you want, you can make the class #Singleton. That is a pseudo scope, and you get no proxy, you get the actual instance that you can work with directly.

If a class is already #Service, then does it need to be #Autowired in Spring Application class?

I'm following a tutorial and they #Service a class which in my mind should make it available to the whole application.
Why are the #Autowire-ing the class in Application?
Application:
#Configuration
#EnableAutoConfiguration // todo why not #SpringBootApplication
#ComponentScan
public class QuoteAppWsApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(QuoteAppWsApplication.class, args);
}
#Autowired
private EventBus eventBus; //
#Autowired // todo This is #Service...why is it be Autowired
private NotificationConsumer notificationConsumer;
NotificationConsumer:
#Service
public class NotificationConsumer implements Consumer<Event<NotificationData>> {
#Autowired
private NotificationService notificationService;
#Override
public void accept(Event<NotificationData> notificationDataEvent) { // .getData() belongs to Event<>
NotificationData notificationData = notificationDataEvent.getData(); //TODO Gets data from Event
try {
notificationService.initiateNotification(notificationData);
} catch (InterruptedException e) {
// ignore
}
}
}
#Service is a specialization of #Component. It is an annotation that tells Spring to include this class as a Bean in the Spring context. You can think of this as telling Spring what to pick up and put into the context during component scanning.
#Autowired is Spring's annotation to inject something from the context. You can think of this as you declaring what you want to get out of Spring. In general, you need to use this annotation on any field, constructor, or setter that you want Spring to invoke to supply you with the object that it's managing for the given type.
To answer your question, yes, you need both to declare what you want put into the context and when you want something out of the context.
Also, your first three annotations can be replaced with #SpringBootApplication. This annotation is a meta-annotation, meaning it's an annotation that it shorthand for including a series of other annotations. It's documented to include, among other things, all three of your annotations.

Java 8 and Spring 4 : Use autowiring in interface

Java 8 added a new feature by which we can provide method implementation in interfaces.
Is there any way in Spring 4 by which we can inject beans in the interface which can be used inside the method body?
Below is the sample code
public interface TestWiring{
#Autowired
public Service service;// this is not possible as it would be static.
//Is there any way I can inject any service bean which can be used inside testWiringMethod.
default void testWiringMethod(){
// Call method of service
service.testService();
}
}
This is a bit tricky but it works if you need the dependency inside the interface for whatever requirement.
The idea would be to declare a method that will force the implemented class to provide that dependency you want to autowire.
The bad side of this approach is that if you want to provide too many dependencies the code won't be pretty since you will need one getter for each dependency.
public interface TestWiring {
public Service getService();
default void testWiringMethod(){
getService().testService();
}
}
public class TestClass implements TestWiring {
#Autowire private Service service;
#Override
public Service getService() {
return service;
}
}
You can created Class utils of application context and use it everywhere even not bean class .
you can have code somethins this :
public class ApplicationContextUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
#Override
public void setApplicationContext(ApplicationContext context) {
ApplicationContextUtil.applicationContext = context;
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
}
and add this to your spring configuration
<bean class="com.example.ApplicationContextUtil" id="applicationContextUtil"/>
now simple to use when you need :
ApplicationContextUtil.getApplicationContext().getBean(SampleBean.class)
this word in web and simple spring app.

Get AOP proxy from the object itself

Is possible to get the proxy of a given object in Spring? I need to call a function of a subclass. But, obviously, when I do a direct call, the aspects aren't applied. Here's an example:
public class Parent {
public doSomething() {
Parent proxyOfMe = Spring.getProxyOfMe(this); // (please)
Method method = this.class.getMethod("sayHello");
method.invoke(proxyOfMe);
}
}
public class Child extends Parent {
#Secured("president")
public void sayHello() {
System.out.println("Hello Mr. President");
}
}
I've found a way of achieving this. It works, but I think is not very elegant:
public class Parent implements BeanNameAware {
#Autowired private ApplicationContext applicationContext;
private String beanName; // Getter
public doSomething() {
Parent proxyOfMe = applicationContext.getBean(beanName, Parent.class);
Method method = this.class.getMethod("sayHello");
method.invoke(proxyOfMe);
}
}
This hack is extremely awkward, please consider refactoring your code or using AspectJ weaving. You may feel warned, here is the solution
AopContext.currentProxy()
JavaDoc. I blogged about it here and here.
AopContext.currentProxy() as suggested by Tomasz will work. A more generic solution, that will work outside of the proxied class is to cast the object to org.springframework.aop.framework.Advised and get .getTargetSource().getTarget()
The former (getting the real object from the proxied object) is something that you should not really need. On the other hand getting the target proxy might be useful in some utility class that inspects existing beans in order to add some feature.
You can use a bean post-processor to set a reference to the proxy on the target bean. It moves the Spring-specifics from your beans to a single class.
Post-Processor
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class SelfReferencingBeanPostProcessor implements BeanPostProcessor {
#Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
#Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof SelfReferencingBean) {
((SelfReferencingBean) bean).setProxy(bean);
}
return bean;
}
}
Context
Register the post-processor in applicationContext.xml.
<bean id="srbpp" class="SelfReferencingBeanPostProcessor"/>
Beans
Each bean must implement SelfReferencingBean to tell the post-processor that it needs a reference to the proxy.
public interface SelfReferencingBean {
void setProxy(Object proxy) ;
}
Now implement setProxy in each bean that needs to call itself through its proxy.
public class MyBean implements SelfReferencingBean {
MyBean proxy;
#Override
public void setProxy(Object proxy) {
this.proxy = (MyBean) proxy;
}
}
You could put this last bit of code into a bean base class if you don't mind casting proxy to bean's type when calling methods directly on it. Since you're going through Method.invoke you wouldn't even need the cast.
With a little work I bet this could be converted to an annotation processor a la #Autowired. Come to think of it, I don't recall if I even tried adding a self-reference using #Autowired itself.
public class MyBean implements SelfReferencingBean {
#Autowired MyBean proxy;
}

Resources