In my application there are three seperate projects for task specifics:
One Java project for service layer and dao layer (using Spring DI) - business.jar
One Java project for WS clients - WSClient.jar
Web project using Spring MVC - MyApp.war
Now my problem is how to bind all projects together because the web app has to get dependencies from the service and DAO from business.jar and services have to get dependencies from WSClient.jar in terms of calling web services. I have to use classpath scan utility of Spring to autowire service dao and controller components from all these three projects.
But getting error because service layer is not in classpath:
factory.NoSuchBeanDefinitionException: No matching bean of type
[com.amex.merchant.site.pop.service.POPRenderService] found for dependency:
expected at least 1 bean which qualifies as autowire candidate for this
dependency. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true),
#org.springframework.beans.factory.annotation.Qualifier(value=pOPRenderService)}
Please suggest how to proceed further
The POJO service layer should not have any dependency on web service clients. There shouldn't be a dependency on web service clients with POJO services, either. The POJO services need to be wrapped with "contract first" web services. Sounds like you're doing something wrong to me.
With that said, you need to create JARs from those projects and add them as dependencies to the other projects that need them. OR you can create a dependency in your IDE between projects and compile them all at once. That's not a Spring thing; it depends on your IDE.
As for your immediate problem, make sure that you have a Spring config somewhere with the <context:component-scan> XML in it. It looks like Spring can't find your pOPRenderService bean. If that's a dependency, it could be a CLASSPATH issue. Neither Spring nor the class loader can find the JAR with that .class file in it to resolve the dependency.
Related
I have a Spring Boot RESTful microservice that a customer would like to nest inside their Spring Boot application.
Could someone tell me whether this is possible?
I was hoping this would be as simple as adding a dependency on my application in the customers maven pom file and then excluding the tomcat dependency since the customer already uses the embedded tomcat.
Thanks,
Ben
Since they already use Spring Boot to start their app, you can simply mark all Spring Boot dependencies as provided in your Maven POM, this would exclude it from the JAR as well as embedded Tomcat and all related dependencies. Also make sure you don't build your JAR as a Spring Boot executable (should be the default if you're not using the spring-boot-maven-plugin).
On the customer side, they would need to include your JAR as a dependency, and possibly add a scanBasePackages property to their #SpringBootApplication, to auto-discover your application classes, if they don't reside in a package under the one that #springBootApplication is on. Also, they'll need to be mindful of any URI collisions between your app and theirs, as the two will be sharing the same environment.
So I have a multi-module Maven project that simply has two child modules: Web, and Service. The Web layer has only one controller and one method in that controller that simply displays the age of a dog on the screen.
Where does the dog come from? Well I have another module that is a 'service' layer that basically contains a Dog store/service, and this dog store actually only contains one Dog object at any given time (this is all for learning purposes).
I need to use Spring's Dependency Injection functionality in my Service module in order to autowire a Dog object into my Dog store, and I obviously need Spring's D.I. functionality in my Web module, in order to autowire a Dog store/service into my Dog controller, but I don't know WHICH POM.xml should contain a Spring dependency.
My question is this: Do I need to put a Spring dependency in both the service module AND the web module? The end project is going to be built from the web module, in fact. The web module will have a dependency for the service module (because I need that Dog Service and Dog object classes).
If I don't include spring as a dependency in my Service-module, then the compiler will freak out when I use an annotation like #Autowire. So this leaves my a bit confused. Which module do I put the spring dependency in?
Perhaps just put the entire Spring Web MVC dependency in the Service module, and let the Web module 'inherit' all the custom service classes, PLUS the downloaded Spring jars? (Since, again, the web-module will have a dependency on the service module). This just seems a little counter-intuitive to me because it's not really the service-module that is dependent on Spring Web MVC. Really, the service module only needs Spring Context. But the confusion here is that the "FINAL" spring context (Dispatcher Servlet, etc) will only be used once, from the Web-module build.
I'm ONLY creating the service-module so that my web-module can inherit those classes I've built, but should the web-module inherit the spring classes from the service-module, or should the web-module actually declare the spring classes in it's own POM.xml? If it is the latter option, then won't the service-module freak out when it sees that I'm using annotations and other things from Spring framework, without having a dependency to it?
I realize that was a lot, but I was trying to be as clear as possible in my situation, and I hope that my question makes sense. Thanks for your answers!
I would recommend adding a parent POM to your application and keep all dependencies defined there and make your web and service modules are child modules. See this for more details
In your parent POM, dependencies are defined something like this,
<dependencyManagement>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.5.RELEASE</version>
</dependency>
</dependencyManagement>
Use above defined dependency in your web and service modules,
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
Also, add service module as a dependency to your web module.
I know a way to see XML based configuration dependency graph (Spring Tool Suite) but that does not work for annotations such as #Autowired and application separated in maven modules. Is there any way we can see that at project level or module level?
The beans dependency graph feature in Spring IDE doesn't support non-XML-based Spring definitions.
There is a "live beans graph" feature that visualizes all the beans in a running Spring application. Maybe that helps in your case.
We have a fairly involved web application written using spring-mvc with a maven build system and would like to harness all the power of Grails for the front end.
So the Grails app will essentially call into the spring-mvc app's service layer to access its business logic and data.
I need some guidance with my architectural approach to this integration at a high level.
From my understanding, I will need to;
- add my spring-mvc app as a compile dependency in my BuildConfig.groovy.
- Expose the service layer objects as service beans in my conf/spring/resources.groovy and inject them into my controllers
Questions:
My spring-mvc app has lots of dependencies of its own (which it obviously has to have) which are causing lots of dependency errors. Should I be setting "transitive=false" in my config and calling all of these in my Grails app?
How should the datasource get configured? I guess I have to integrate the applicationContext of my spring-mvc app by calling it from my Grails applicationContext and hope it all bootstraps nicely?
So the Grails app will essentially call into the spring-mvc app's service layer to access its business logic and data
Can you be a bit more specific about which components of the Spring MVC you want to use from Grails, is it just the services and datasource?
I will need to add my spring-mvc app as a compile dependency in my BuildConfig.groovy
yes
Expose the service layer objects as service beans in my conf/spring/resources.groovy
Although you could make the Spring beans known to your Grails app by defining them individually in resources.groovy, this is unnecessary because you've already defined them in an Spring XML file (presumably) in the Spring MVC project.
Instead you can use the importBeans method of the BeanBuilder to import the Spring beans defined in this XML file into the Grails app. Once you've added the Spring MVC project as a dependency of your Grails app, the Spring XML file should be on your classpath, so all you need to do is add the following to resources.groovy
beans = {
importBeans('classpath:/path/to/file/applicationContext-services.xml')
}
How should the datasource get configured?
A Spring bean named dataSource defines the datasource that a Grails app uses. In a standard Grails app, this bean is created based on the configuration in DataSource.groovy. If your Spring MVC app defines a bean with this name, then this should be used instead after making the changes above. To be sure that Grails is using the datasource from your Spring MVC app rather than whatever is in DataSource.groovy, I guess you could delete the contents of the latter.
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;