How to pass value from #Value in service from another service? - java

I have a interface witch use a variable tableName
public interface TableNameService {
void printName();
}
#Serive
public class TableNameServiceImpl implements TableNameService{
#Ovveride
public void printName() {
System.out.println(tableName);
}
}
This interface I inject to other services like OracleService etc and initialize tableName in services through #Value.
For example:
#Service
public class OracleService {
private TableNameService service;
#Value("${tableName}")
private String tableName;
public void print() {
service.printName()
}
}
How to pass field from OracleService to TableNameService during injection TableNameServiceImpl so as not to pass it in the method parameters and not to put it down all the time with your hands?

A common reason why dependency injection became so popular is because it avoids boilerplate code where you need to pass from one method into the other the same instances and values.
In your case here you could also take advantage of DI by adding #Value("${tableName}") private String tableName; in your TableNameServiceImpl class and autowiring this service class inside OracleService.
#Service
public class TableNameServiceImpl implements TableNameService{
#Value("${tableName}")
private String tableName;
#Ovveride
public void printName() {
System.out.println(tableName);
}
}
And then you can have
#Service
public class OracleService {
#Autowired
private TableNameService service;
public void print() {
service.printName()
}
}

Related

How to automatically inject implementation based on Generics

I have a Service class defined like this,
#RequiredArgsConstructor
class SomeService<T extends AbstractResponse> {
private final ValidationService<T> validationService;
....
}
And I have two kinds of AbstractResponse, ResponseA and ResponseB and have a validation service defined for both of them.
#Service("aValidationService");
class AValidationService<ResponseA> implements ValidationService<ResponseA> {
....
}
and
#Service("ValidationService");
class BValidationService<ResponseB> implements ValidationService<ResponseB> {
....
}
Right now spring is throwing an error because it's not able to deduce the implementation of ValidationService to use in SomeService as there are two implementations of it. How do I make spring deduce the correct implementation based on the type of AbstractResponse?
Hope that I understood your requirements.
You can not automatically inject, when you have (2) of the same kind. In this case ValidationService.
You could inject #ValidationServiceA, or #ValidationServiceB, or a List<ValidationServiceI> and then return the one you want based on a <T> type you care about:
The solution below highlights that.
The method getGenericParameter() is used to return the <T> parameter. This is to avoid the use of Reflection.
The method methodWhichDeterminesWhichServiceToUseBasedOnResponseType to used to determine which ValidationService to use based on the input that you require.
You can find the complete solution below, including a verification Test.
import org.springframework.stereotype.Service;
#Service
public class ValidationServiceA implements ValidationServiceI<ResponseA>{
#Override public Class<ResponseA> getGenericParameter() {
return ResponseA.class;
}
public void print(){
System.out.println("Service A");
}
}
#Service
public class ValidationServiceB implements ValidationServiceI<ResponseB>{
#Override public Class<ResponseB> getGenericParameter() {
return ResponseB.class;
}
public void print(){
System.out.println("Service B");
}
}
public interface ValidationServiceI<T>{
Class<T> getGenericParameter();
void print();
}
#Service
public class ServiceWhichCallsOthers {
#Autowired
private List<ValidationServiceI> validationServices;
public <T> ValidationServiceI<T> methodWhichDeterminesWhichServiceToUseBasedOnResponseType(T responseType){
Optional<ValidationServiceI> validationServiceSupportingResponse = validationServices.stream().filter(validationServiceI -> validationServiceI.getGenericParameter().equals(responseType)).findFirst();
return validationServiceSupportingResponse.get();
}
public void callValidationServiceA(){
methodWhichDeterminesWhichServiceToUseBasedOnResponseType(ResponseA.class).print();
}
public void callValidationServiceB(){
methodWhichDeterminesWhichServiceToUseBasedOnResponseType(ResponseB.class).print();
}
}
#SpringBootTest
public class ServiceWhichCallsOthersIT {
#Autowired
private ServiceWhichCallsOthers serviceWhichCallsOthers;
#Test
public void validateBasedOnResponseType(){
Assertions.assertEquals(ValidationServiceA.class, serviceWhichCallsOthers.methodWhichDeterminesWhichServiceToUseBasedOnResponseType(ResponseA.class).getClass());
Assertions.assertEquals(ValidationServiceB.class, serviceWhichCallsOthers.methodWhichDeterminesWhichServiceToUseBasedOnResponseType(ResponseB.class).getClass());
serviceWhichCallsOthers.callValidationServiceA();
serviceWhichCallsOthers.callValidationServiceB();
}
}

Accessing advised objects methods from a default implementation

I am trying to find out what is the usability of inter-type declarations in Spring AOP but I am stuck with one problem that makes it a bit useless.
HelloMixin aspect declares that advised services implement HelloService and provides a default implementation HelloServiceImpl.
#Aspect
public class HelloMixin {
#DeclareParents(value = "xxx.xxx.services.*+", defaultImpl = HelloServiceImpl.class)
static HelloService mixin;
}
Then I have two services:
#Service
public class FirstService {
private String name = "First";
public String getName() {
return name;
}
}
#Service
public class SecondService {
private String name = "Second";
public String getName() {
return name;
}
}
New interface:
public interface HelloService {
public void sayHello();
}
Default implementation:
public class HelloServiceImpl implements HelloService {
private String getName() {
return "defaultName";
}
#Override
public void sayHello() {
System.out.println("Hello " + getName());
}
}
Execution:
#Autowired
#Qualifier("firstService")
HelloService firstService;
#Autowired
#Qualifier("secondService")
HelloService secondService;
public String hello() {
firstService.sayHello();
secondService.sayHello();
}
Result:
INFO: Hello defaultName
INFO: Hello defaultName
This concept could be really cool if I had a way to use getName methods from advised objects. Otherwise I do not see any sense to use it if I am not able to write any object dependent logic. Is it possible? In other words I would like to see the result:
INFO: Hello First
INFO: Hello Second
You could do it using #DeclareMixin instead, that allows to use a factory method for creating the delegate.
#Aspect
public class HelloMixin {
#DeclareMixin("xxx.xxx.services.*+")
public HelloService createHelloService(Object target) {
return new HelloServiceImpl(target);
}
}
public class HelloServiceImpl implements HelloService {
private Object target;
public HelloServiceImpl(Object target) {
this.target = target;
}
#Override
public void sayHello() {
System.out.println("Hello " + getNameFromTarget());
}
private String getNameFromTarget() {
// call to this.target.getName()....
}
}
Spring AOP don't support #DeclareMixin annotation, see https://jira.spring.io/browse/SPR-11350 but I added it to JDAL 2.0 in a small independent module jdal-aop, so I encourage you to try it.

Call spring inject class from a static method from another class

Well, i have a class with #Component anotation, this class makes some selects in database, see:
#Component(value = "parametroRelatorioHelper")
public class ParametroRelatorioHelper {
#Autowired
private BasicDAO dao;
public ParametroRelatorio getParametroByNome(String nome) {
List<ParametroRelatorio> parametros = (List<ParametroRelatorio>) dao
.findByNamedQuery(ParametroRelatorio.FIND_BY_NOME,
new NamedParams("nome", nome));
if (parametros.size() > 0)
return parametros.get(0);
else
return null;
}
public List<ParametroRelatorio> getAll() {
return (List<ParametroRelatorio>) dao
.findByNamedQuery(ParametroRelatorio.FIND_ALL);
}
public BasicDAO getDao() {
return dao;
}
public void setDao(BasicDAO dao) {
this.dao = dao;
}
}
Now, i have a "Helper" class, where user can call your method directly (static method) but i need call a method from ParametroRelatorioHelper, see:
public class ReportHelper {
public static void call(){
//how can i do it without #Component injection
parametroRelatorioHelper.getAll();
}
}
It sounds like your architecture is incorrect, instead the ReportHelper should be a component too and the dependencies should be injected in it, otherwise it collides with the idea of the Spring IOC, helper methods should not rely on components on services...

Spring runtime use swap bean class

#Component
#Qualifier("SUCCESS")
public class RandomServiceSuccess implements RandomService{
public String doStuff(){
return "success";
}
}
#Component
#Qualifier("ERROR")
public class RandomServiceError implements RandomService{
public String doStuff(){
throw new Exception();
}
}
the calling code
#Controller
public class RandomConroller {
#Autowired
private RandomService service;
public String do(){
service.doStuff();
}
}
What I need to do here is to have them swapped based on a value can be retrieved from some custom http header from a http request. Thank you!
I'm totally agree with Sotirios Delimanolis that you need to inject all the implementations and choose one of them at runtime.
If you have many implementations of RandomService and don't want to clutter RandomController with selection logic, then you can make RandomService implementations responsible for selection, as follows:
public interface RandomService{
public boolean supports(String headerValue);
public String doStuff();
}
#Controller
public class RandomConroller {
#Autowired List<RandomService> services;
public String do(#RequestHeader("someHeader") String headerValue){
for (RandomService service: services) {
if (service.supports(headerValue)) {
return service.doStuff();
}
}
throw new IllegalArgumentException("No suitable implementation");
}
}
If you want to define priorities for different implementations, you may use Ordered and put the injected implementations into a TreeSet with OrderComparator.
Qualifier should be used to specify which instance of the interface you want injected in the field after specifying different IDs for each one. Following #Soritios' advice you could do something like:
#Component("SUCCESS")
public class RandomServiceSuccess implements RandomService{
public String doStuff(){
return "success";
}
}
#Component("ERROR")
public class RandomServiceError implements RandomService{
public String doStuff(){
throw new Exception();
}
}
#Component
public class MyBean{
#Autowired
#Qualifier("SUCCESS")
private RandomService successService;
#Autowired
#Qualifier("ERROR")
private RandomService successService;
....
if(...)
}
...or you could obtain just the instance you want from the application context based on your parameter:
#Controller
public class RandomConroller {
#Autowired
private ApplicationContext applicationContext;
public String do(){
String myService = decideWhatSericeToInvokeBasedOnHttpParameter();
// at this point myService should be either "ERROR" or "SUCCESS"
RandomService myService = applicationContext.getBean(myService);
service.doStuff();
}
}
You can just inject both and use the one you need.
#Inject
private RandomServiceSuccess success;
#Inject
private RandomServiceError error;
...
String value = request.getHeader("some header");
if (value == null || !value.equals("expected")) {
error.doStuff();
} else {
success.doStuff();
}

The decorator pattern and #Inject

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.

Categories

Resources