how to call service inside service layer - java

in my service layer
public class MyServiceLayerImpl{
public void method1(){
MyServicelayer.method(); //is this correct?
}
public void method2(){
}
#Autowired
MyServiceInterface MyServiceLayer;
}
if i have method inside service layer that need to call another service inside service layer. i cannot use this._method ,because, i'm using AOP for caching. In order for the caching to work, i have to use #Autowired to get the service. Therefore, is the above style ok?
i get below error
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.company.iss.services.MyServiceLayerImpl#85aedd': Autowiring of fields failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.company.iss.services.MyServicelayer com.company.iss.services.MyServiceLayerImpl.MyServiceLayer; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.company.iss.services.MyServiceLayer] is defined: Unsatisfied dependency of type [interface com.company.iss.services.MyServiceLayer]: expected at least 1 matching bean

It's hard to tell from the weird formatting and naming, but if you want to call one service from another:
public interface MasterService {
void someMethod();
}
public class MasterServiceImpl implements MasterService {
private OtherService otherService;
public void someMethod() {
this.otherService.someCallOnOtherService();
}
#Autowired
public void setOtherService(OtherService otherService) {
this.otherService = otherService;
}
}
Now, you must have configured both MasterServiceImpl and whatever implements OtherService. There are many ways to do this, the most popular being explicitly in your XML configuration with annotation-based configured a close second.
Also note that AOP tends to be very flaky if you aren't using interfaces. In your code, your Impl doesn't actually implement anything. I would recommend against that.

Apart from having an uppercase variable and no colon - it's fine.
You would, of course, need to define your class as a bean. Either by using the #Service (or another stereotype) annotation on it, or using <bean> in applicationContext.xml (see here for the annotation-based config introduced in spring 2)
Another thing: your member variables should be lowercase, not uppercase.

Related

Autowiring conflict in spring core with the xml configuration

Taking as reference the post Spring #Autowired and #Qualifier
We have this example to fix the autowiring conflict :
public interface Vehicle {
public void start();
public void stop();
}
There are two beans, Car and Bike implements Vehicle interface.
#Component(value="car")
public class Car implements Vehicle {
#Override
public void start() {
System.out.println("Car started");
}
#Override
public void stop() {
System.out.println("Car stopped");
}
}
#Component(value="bike")
public class Bike implements Vehicle {
#Override
public void start() {
System.out.println("Bike started");
}
#Override
public void stop() {
System.out.println("Bike stopped");
}
}
#Component
public class VehicleService {
#Autowired
#Qualifier("bike")
private Vehicle vehicle;
public void service() {
vehicle.start();
vehicle.stop();
}
}
That's a very good example to fix this problem.
But when I have the same problem but without those balises in the application context:
<context:component-scan></context:component-scan>
<context:annotation-config></context:annotation-config>
All the issues are solved by using the #Qualifier annotation, but in my case we don't use the balise that permit to use annotation.
The question is :
How can I fix this issue just using the configuration in application context, that's it, without using annotations?
I searched a lot and I found people talking about autowire attribute in the bean declaration <bean id="dao" class="package.IDao" autowire="byName"></bean> and I need more explanation about it.
How can I fix this issue just using the configuration in application
context?
You could use the qualifier tag like below (see https://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/beans.html#beans-autowired-annotation-qualifiers)
<context:annotation-config/>
<beans>
<bean class="your_pkg_route.Vehicle">
<qualifier value="bike"/>
</bean>
</beans>
</context:annotation-config>
I found people talking about autowire attribute in the bean
declaration and I need more explanation about it
Using Annotation
#Autowired used on a bean declaration method injects the defined dependencies by (another) declared beans. Now, if your dependencies are in the same context of your application, you don't need to use the #Autowired annotation at all because Spring is able to figure them out by itself. So, if your dependencies are outside your applicatoin context then you can use it.
For example, take as reference the below code:
#Autowired
#Bean
public MyBean getMybean(Dependency1 depdency1, Dependency2 depdency2) {
return new MyBean(depdency1.getSomeStuff(), depdency2.getSomeOtherStuff());
}
Here, #Autowired will find an instance of Dependency1 and Dependency2 and will provide them for the creation of an instance of MyBean.
Using xml configuration
From Pro Spring 5... Spring supports five modes for autowiring.
byName: When using byName autowiring, Spring attempts to wire each property to a bean of the same name. So, if the target bean has a property named foo and a foo bean is defined in ApplicationContext, the foo bean is assigned to the foo property of the target.
byType: When using byType autowiring, Spring attempts to wire each of the
properties on the target bean by automatically using a bean of the same type in
ApplicationContext.
constructor: This functions just like byType wiring, except that it uses constructors rather than setters to perform the injection. Spring attempts to match the greatest numbers of arguments it can in the constructor. So, if your bean has two constructors, one that accepts a String and one that accepts String and an Integer, and you have both a String and an Integer bean in your ApplicationContext, Spring uses the two-argument constructor.
default: Spring will choose between the constructor and byType modes
automatically. If your bean has a default (no-arguments) constructor, Spring uses
byType; otherwise, it uses constructor.
no: This is the default
So, in your case you would need to do something like this (BUT, I would NOT recommend it. Why?, you would need to declare Vehicle class as a bean and a component which is not correct, see Spring: #Component versus #Bean. On the other hand I'm not sure if you could use it just declaring it as a bean):
// xml config
<context:annotation-config/>
<beans>
// use the primary tag here too! in order to say this the primary bean
// this only works when there are only two implementations of the same interface
<bean id="bike" primary="true" class="your_pkg_route.Bike"/>
<bean id="car" class="your_pkg_route.Car"/>
<bean autowire="byName" class="your_pkg_route.VehicleService"/>
<beans>
</context:annotation-config>
// VehicleService
#Component
public class VehicleService {
private Vehicle bike; // call attribute 'bike' so it is autowired by its name
public void service() {
//...
}
}
As you can see there is a lot of complications trying to do this using xml config, so I would recommend you to use the annotation option if possible.
Related posts:
Why do I not need #Autowired on #Bean methods in a Spring configuration class?
Difference between #Bean and #Autowired
PS: I have not tested any of the posted codes.
You can use #Primary instead of #Qualifier
#Primary
#Component(value="bike")
public class Bike implements Vehicle {
we use #Primary to give higher preference to a bean when there are multiple beans of the same type.
We can use #Primary directly on the beans
You can also set primary attribute in XML:
property has primary attribute:
<bean primary="true|false"/>
If a #Primary-annotated class is declared via XML, #Primary annotation metadata is ignored, and is respected instead.

No qualifying bean, expected single matching bean but found 2

I searched on both the internet and on stack overlow but can't seem to find a solution to my problem:
Unable to find bean reference for type 'class com.consol.citrus.http.client.HttpClient'Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.consol.citrus.http.client.HttpClient' available: expected single matching bean but found 2: server1BasicAuthClient,server2BasicAuthClient
To sketch some background information: I have to make a small application using Spring 5 and Citrus Framework to automate our integration tests.
I defined as following my Beans:
#Configuration
public class EndpointAuthentication {
public String server1Host;
public int server1Port;
public String server2Host;
public int server2Port;
#Bean(name="server1BasicAuthClient")
public com.consol.citrus.http.client.HttpClient server1BasicAuthClient() throws Exception {
return CitrusEndpoints.http()
.client()
.requestUrl(String.format("http://%s:%s/", server1Host, server1Port))
.requestFactory(sslRequestFactory(server1Host,server1Port))
.build();
}
#Bean(name="server2BasicAuthClient")
public com.consol.citrus.http.client.HttpClient server2BasicAuthClient() throws Exception {
return CitrusEndpoints.http()
.client()
.requestUrl(String.format("http://%s:%s/", server2Host, server2Port))
.requestFactory(sslRequestFactory(server2Host,server2Port))
.build();
}
}
And I tried to inject my Bean like this,
public class AuthenticationIT {
#Autowired
#Qualifier("server1BasicAuthClient")
#CitrusEndpoint
private HttpClient server1BasicAuthClient;
#Autowired
#Qualifier("server2BasicAuthClient")
#CitrusEndpoint
private HttpClient server2BasicAuthClient;
....
}
Any ideas where and how to fix the issue ?
Thanks in advance.
If you intend to express annotation-driven injection by name, do not primarily use #Autowired, even if is technically capable of referring to a bean name through #Qualifier values. Instead, use the JSR-250 #Resource annotation, which is semantically defined to identify a specific target component by its unique name, with the declared type being irrelevant for the matching process.
As a specific consequence of this semantic difference, beans that are themselves defined as a collection or map type cannot be injected through #Autowired, because type matching is not properly applicable to them. Use #Resource for such beans, referring to the specific collection or map bean by unique name.
#Autowired applies to fields, constructors, and multi-argument methods, allowing for narrowing through qualifier annotations at the parameter level. By contrast, #Resource is supported only for fields and bean property setter methods with a single argument. As a consequence, stick with qualifiers if your injection target is a constructor or a multi-argument method.
Try to set using value instead of name OR use #Primary
#Bean(value="server1BasicAuthClient")
#Bean(value="server2BasicAuthClient")
Refer 1 Refer 2

Autowired failing to load service into class

I'm receiving a null pointer exception when operating on my service because my service is not being Autowired into the class. I've implemented this class's repository and service exactly the same as others in this application and I haven't had this problem before. The class does in fact warn about issues with the Autowire but I'm not sure how to fix them:
Autowired members must be defined in valid spring bean
Again, this is set up the same as other classes and I do not have this issue. Within the service class, it complains that the repository cannot be autowired into the constructor because there are multiple beans of the same type. My other service class shows this warning as well but does not have problems being Autowired into classes and operated upon. Definitions below, please ask for any other context that would be helpful.
//TransactionCategoryRepository.java
#Repository("transactionCategoryRepository")
public interface TransactionCategoryRepository extends
CrudRepository<TransactionCategory, Integer> {
}
--
//TransactionCategoryService.java
#Service("transactionCategoryService")
public class TransactionCategoryService {
private TransactionCategoryRepository transactionCategoryRepository;
#Autowired
public TransactionCategoryService(TransactionCategoryRepository repository) {
this.transactionCategoryRepository = repository;
}
public void saveTransactionCategory(TransactionCategory transactionCategory) {
transactionCategoryRepository.save(transactionCategory);
}
}
--
//Utilities.java
public class PlaidUtilities {
private Logger logger =
LoggerFactory.getLogger(PlaidUtilities.class.getSimpleName());
private PlaidClient mPlaidClient;
#Autowired
TransactionCategoryService mTransactionCategoryService;
...
The multiple bean warning is thrown on respository in TransactionCategoryService.java and the Autowired definition warning is thrown in Utilities.java. The breaking null pointer exception error occurs later in Utilities.java when operating on mTransactionCategoryService.
Unless you need them, take the names out of the #Service and #Repository annotations. I've found it just makes things awkward.
The other thing that might be wrong is that you're not scanning those packages. You can change that in your main class by altering the boot application attribute to #SpringBootApplication(scanBasePackages={"your.package.here"})
Have a look here at this question where they detail it

Having Spring's IoC container instantiate beans with zero config (like Google Guice's behaviour)

I have a hobby-project which I would like to migrate to Spring.
As an example I have the following classes:
public class OtherBean {
public void printMessage() {
System.out.println("Message from OtherBean");
}
}
public class InjectInMe {
#Inject OtherBean otherBean;
public void callMethodInOtherBean() {
otherBean.printMessage();
}
}
However as I read the documentation, I must annotate all classes to be managed by Spring with an annotation like #Component (or others that are similar).
Running it with the following code:
public class SpringTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.refresh();
InjectInMe bean = context.getBean(InjectInMe.class);
bean.callMethodInOtherBean();
}
}
Gives me the error:
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [somepackage.InjectInMe] is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:371)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:331)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:968)
at somepackage.SpringTest.main(SpringTest.java:10)
My question is: is there a way to make Spring manage any class I ask the ApplicationContext to instantiate without me having to register them in an Annotated Config (or XML config)?
In Guice I can just inject into the class
public class GuiceTest {
static public class GuiceConfig extends AbstractModule {
#Override
protected void configure() {}
}
public static void main(String[] args) {
Injector injector = Guice.createInjector(new GuiceConfig());
InjectInMe bean = injector.getInstance(InjectInMe.class);
bean.callMethodInOtherBean();
}
}
Gives me the output:
Message from OtherBean
Is there anyway I can make Spring work like Guice? As in make Spring inject my beans without me having to register or scan packages for classes annotated with #Component-like annotations?
Any Spring gurus have a way to solve this problem?
My question is: is there a way to make Spring manage any class I ask
the ApplicationContext to instantiate without me having to register
them in an Annotated Config (or XML config)?
No, it's not possible. This is simply not how Spring is designed. You must either implicitly (e.g. scan + annotation) or explicitly (e.g. XML bean definition) register your beans.
The least you can do is something like:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(OtherBean.class);
context.register(InjectInMe.class);
context.refresh();
There are a few ways to provide bean definitions for Spring's ApplicationContext:
Use component scanning and annotate your types with #Component or one of its meta annotations (#Service, #Controller, etc.)
Define a <bean> in XML configuration or a #Bean in Java configuration (or whatever other type of explicit configuration).
Use a BeanDefinitionRegistryPostProcessor to register beans directly on a BeanDefinitionRegistry.
Some ApplicationContext subtypes implement BeanDefinitionRegistry, so you can register bean definitions with them directly.
The beans generated from these bean definitions will be available when injection is required. You wouldn't want (at least IMO) your container to instantiate a type without you telling it somehow that it is OK.
You must either declare the class as a #Component, or whatever it may be, or you must provide an xml definition. If you don't define the bean, how is Spring supposed to know what to do? For the properties of a class, e.g. MyController has a private service MyService. If you put the #Autowired tag above the service instantiation, Spring will automatically inject this server into your controller, which is what your comment about #Inject seems to hint at. However, in order to autowire, you must define a bean for that class, which means you must use either the #Component/#Controller, etc annotation configuration or an xml bean configuration.

Spring How to autowire a component without using #Component or other derivatives

I would like to autowire a component (still using the #Autowired annotation), but not require it to have the #Component (or other similar annotations) on it. How would I do this?
public class A {
#Autowired
private class B b;
}
#Component
public class B {
}
This would be convenient in order to allow autowiring of class A without requiring the creation of A, unless we needed it (in otherwise on the fly by reflection using the class name).
Injection and autowiring do not require #Component. They require beans. #Component states that the annotated type should have a bean generated for it. You can define beans in other ways: with a <bean> declaration in an XML context configuration, with a #Bean method in a #Configuration class, etc.
Your last sentence doesn't make much sense. You can't process injection targets in a bean without creating a bean. You also can't inject a bean without creating it. (Applied to scopes, bean may refer to the target source/proxy and not the actual instance.) Perhaps you want #Lazy.
I don't sure, If I correctly understood to your question. But if you want inject bean B without marking bean A via some annotation, or xml definition, you can use SpringBeanAutowiringSupport
public class A {
#Autowired
private class B b;
public A{
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}
}

Categories