How does precedence between multiple provider takes place in Google Guice? - java

I am trying Google Guice as Dependency Injection framework for my new project and shifting from spring.
I have to write multiple providers using #Provides, where instance created from one provider will be used as an input to other providers in the separate modules (sometimes the same module).
For binding the instance generated from the module, I am using Guice's
#BindingAnnotation
to create a custom annotation.
I just wanted to know how does the precedence works in Google Guice?
Like in spring we had a #Dependson annotation for bean creation, is there an alternative in Guice or Guice smart enough to generate a dependency graph by itself?
Does Binding the instances of providers using annotation created from #BindingAnnotation enough?

[is] Guice smart enough to generate a dependency graph by itself?
I'm not familiar with Spring, but my gut-feeling is Yes.
Does Binding the instances of providers using annotation created from
#BindingAnnotation enough?
As long as the provider has been annotated as providing something (using #Provides), Guice will use that annotation as a default, unless otherwise overridden inside a module.
However, using BindingAnnotations does include some code in a Module to bind it together,
https://github.com/google/guice/wiki/BindingAnnotations
bind(CreditCardProcessor.class)
.annotatedWith(PayPal.class)
.to(PayPalCreditCardProcessor.class);
So I suspect that Binding Annotations based annotations have stronger strength then #Provides and as long as you have the counterpart in the module, is more then enough to bind your providers together.

Related

Where to specify #Transactional annotation in a Spring Boot app?

In the context of a recent Spring Boot app (v. 2.7.0), there are a number of options for where the #Transactional annotation is applied
Controller or Service?
Almost universally it seems that service is recommended, but it's not entirely clear why.
Implementation class or interface?
Assuming we choose to apply the annotation to our services and those services implement an interface, should we annotate the service interface or the implementation class?
In older versions of the Spring docs, it was recommended to annotate the class
Spring recommends that you only annotate concrete classes (and methods of concrete classes) with the #Transactional annotation, as opposed to annotating interfaces. You certainly can place the #Transactional annotation on an interface (or an interface method), but this works only as you would expect it to if you are using interface-based proxies. The fact that Java annotations are not inherited from interfaces means that if you are using class-based proxies (proxy-target-class="true") or the weaving-based aspect (mode="aspectj"), then the transaction settings are not recognized by the proxying and weaving infrastructure, and the object will not be wrapped in a transactional proxy, which would be decidedly bad.
But this advice does not appear in the 5.2.X version of the docs, so I'm wondering if it still applies? Based on my testing it seems that applying the #Transactional annotation to interfaces does work in a Spring Boot app with the default proxying behaviour.
#Transactional is most commonly used at service level, though there is nothing stopping you from making your controller methods transactional. It really depends on how you structure your application.
IMHO making your service layer transactional is a better approach. It is typically at this level that you might be calling other persistence methods (DAOs, repositories, etc). There could be reads/writes across multiple tables, so it makes the service layer a good place to define transaction boundaries.

How to Configure Dependency Injection in a Library Project?

How to Configure Dependency Injection in a Library Project?
Let me illustrate this question with the following example.
Maven Library Project
ReservationAPI
com.example.reservation-api
This project contains a convenience class called ReservationApiClient which uses a RestTemplate (from the Spring Framework) for making HTTP calls.
Is it possible to make the RestTemplate field #Autowired in this library project instead of instantiating it myself?
Maven Executable Project
org.company.application
This project is a Spring Boot application and uses the above ReservationAPI as a dependency. This app will create a #Bean for the convenience class ReservationApiClient contained in that library and will then execute its public methods which in turn make HTTP requests.
What is a good strategy and/or best practices for the scenario described above?
You can do this if you include autowiring in your library project although that means it would always need to be used with a Spring application context to get the value unless you also have getter/setter methods to use as well. However, I don't think using RestTemplate as an autowired object makes sense since there is nothing specific about a RestTemplate and unless you name the beans there is only one bean definition for a class. All of the methods for the RestTemplate require the URI there anyhow. So in this case I would just use the bean for your ReservationApiClient in your application.
One other way to do it is if you want to include Spring dependencies in your library (which I guess you already are by using RestTemplate) you can declare your ReservationApiClient as a #Service or #Component and then use the #ComponentScan annotation in your main Spring Boot project to search that library for components to include in the bean registry.
Another option is to use a feature like Spring Boot's Autoconfigure to create factories that use third party libraries and configure them per properties in your application settings. The auto configuration documentation would be a good place to start with this. You can see the starter projects they have on GitHub and then the associated Autoconfigure classes they have associated with these.
Let me know if any of this does not make sense.

Classpath scanning of dependencies

I have a 3-tier application: web-service, service-layer and domain-layer. The web service is present in a web application (WAR). The service-layer and domain-layer are two JAR projects. The dependencies are:
web-service --> service-layer --> domain-layer
In the service layer, the services are annotated with #Service. In the domain-layer, the DAOs are annotated with #Repository. The web service implementation class uses the services of the service-layer JAR, so it keeps one instance of each service which is automatically injected (#Autowired).
The dependencies are well defined in my POMs. When I deploy my WAR on Tomcat, I get the following exception:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.mycompany.project.services.MyService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:952)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:821)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:735)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:551)
... 37 more
I quote from one relevant part in the Spring docs:
The scanning of classpath packages requires the presence of
corresponding directory entries in the classpath. When you build JARs
with Ant, make sure that you do not activate the files-only switch of
the JAR task.
I've checked and the service-layer JAR is present in the WEB-INF/lib directory.
Any idea?
Thanks
EDIT: I have only one context file which is located in the web-service layer project (WAR) under src/main/webapp/WEB-INF. In this context, I've enabled classpath scanning as follows:
<context:component-scan base-package="com.mycompany.project" />
The package com.mycompany.project is the base package of my project, under which there are the web-service (com.mycompany.project.server), service-layer (com.mycompany.project.services) and domain-layer (com.mycompany.project.domain) packages.
I've solved the issue. I don't understand why what I've done was causing such an issue. Each service implements an interface that defines its public methods. In my web service implementation class, the references to the services used the implementation classes and not the interfaces. I just changed them to use the interface, and I don't get the issue anymore. Could anyone explain me what's wrong with using the services implementation classes instead of the interfaces for the autowiring?
This is an answer for your EDIT:
The reason why referring to the interface worked but the concrete implementation failed is probably to do with the dynamic proxies that Spring creates for cases where you have your services annotated with #Transactional etc. What happens in such cases is that the type of your beans are not the implementation type anymore, but wrap around your impementation type. So when you have #Autowired by implementation type, it just cannot find it by type (which is the default).
Your fix is very appropriate, as a dynamic proxy continues to derive from the interfaces that you have defined for your implementation and so can inject by interface type - the reference that I have provided does a better job explaining this.
make sure you used <context:component-scan base-package="your.service.package"/>
check your autowired strategy is byName or byType; if byName, the Service annotation's name value should be right.
if problem still exist, check spring's log, it will print all found components' name, you could know the service is founded or not.
Can you show your component scanning configuration? If this is not set up correctly then Spring may not be discovering your service.
You want something like:
<context:component-scan base-package="your.service.package"/>
Edit:
I think the problem is that your #Service annotation is on the interface rather than implementation class.
If you annotate your service implementation then your web controller can use either:
#Autowired
private ExampleService service;
or
#Autowired
private ExampleServiceImpl service;

How to expose JAX-RS "DTO"s from entities for REST-Clients?

I have a Java EE 6 web application that offers it's data via a JAX-RS REST web service.
The entities are annotated with the JPA annotations as well as with the javax.xml.bind JAX annotations.
My aim is to assemble a client-jar out of my web-app project that contains the JAX-RS annotated "DTO" classes to be used for JAX unmarshalling in clients of my web-app.
Putting the raw entities in the client jar is not an option because of the JPA annotations, which would lead to bogus dependencies for the client.
Is there a way for doing this without writing the JAX-RS classes twice, for the web-app and the clients?
I thought of annotation processing and killing all JPA annotations in the entities, that's quite techy, but not very handy.
My second idea is to extract an interface of the needed getters/setters of the entities. The question here is how to handle the JAX annotations that are placed at the class members and at the getters.
Both ways seem to work somehow. But is there a general purpose solution for that task?
Hint: yes, i'm aware of the way to expose the JPA-Entities directly via rest and its coupling drawbacks to evolution etc =)
You could supply the JPA metadata via XML (http://java.sun.com/xml/ns/persistence/orm_2_0.xsd) instead of annotations. This would give you the mapping without the class path dependency.
http://java.dzone.com/articles/persisting-entity-classes

Something like EJB wiring in Spring for non EJB's

I've noticed recently that spring can wire up my ejb's for me if I annotate the ejb with #Interceptors(SpringBeanAutowiringInterceptor.class). I've never actually done this so don't know the details.
I was wondering, is there a way to get this to work with other kinds of beans, for example, #WebService annotated ones as well.
At the moment in my web service classes (because the application server manages them) I have to load the dependencies from the BeanFactory and would thus prefer to have them autowired.
I know I could use the #Configurable annotation but am not particularly keen to have to specify and agent on the VM.
Is this possible?
Once again, spring has thought of this use case and catered for it!
The problem is that #WebService is not a spring annotation, it is a JAX-WS annotation and thus classes that are annotated with #WebService to be exposed as web services are not managed by spring, but their life cycle is managed by JAX-WS.
The way to handle this case is to have the JAX-WS managed bean extend org.springframework.web.context.support.SpringBeanAutowiringSupport - this will enable the #Autowire annotation, for example, to work in this bean. see here for more information
Yes, of course. There's #WebService, #Repository, #Controller, #Service, #Endpoint, and other annotations in Spring. Here's an example.

Categories