I am new to Spring / Spring Boot, so please pardon if what I am asking is trivial.
I have created Spring Boot application which exposes the REST endpoint:
package com.atomic.contentguard;
...
#Controller
#RequestMapping("/rest")
public class AcgController {
#RequestMapping(value="/acg-status",method=RequestMethod.GET)
#ResponseBody
public String getStatus(){
return "Hi there!";
}
}
It all works fine when you run it as standalone Spring Boot application, the endpoint is testable by going to http://localhost:8080/rest/acg-status.
What I want to achieve is to "bring it" into another application, which would be including my application as a dependency in the pom.xml, expecting this REST endpoint to show up in it.
What I've done so far is included it in another project pom.xml as:
</dependencies>
...
<dependency>
<groupId>com.atomic</groupId>
<artifactId>contentguard</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
And then included it in that other application #ComponentScan section of config file:
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = {"com.atomic.contentguard"})
public class EnvInfoWebConfig extends WebMvcConfigurerAdapter {
}
It does not however show up when you run target application:
No mapping found for HTTP request with URI [/other-application-context/rest/acg-status] in DispatcherServlet with name 'envinfo-dispatcher'
What am I missing / doing wrong?
You can do this simply by using the spring boot Application Launcher class in your main project as below (You don't need WebMvcConfigurerAdapter class):
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
#SpringBootApplication
#ComponentScan(basePackages = { "com.atomic.contentguard"})
public class AcgLauncher extends SpringBootServletInitializer {
//This method is required to launch the ACG application
public static void main(String[] args) {
// Launch Trainserv Application
SpringApplication.run(AcgLauncher.class, args);
}
}
Spring Boot uses this class during the server startup and scans the specified packages for all spring components (controllers, services, components).
Related
A web application I've been working on recently the past like 2 weeks maybe for whatever reason when I finally tested it - won't seem to even enter the method that I have to return a JSON list of objects. I have included the Jackson library and Spring Boot Web, Tomcat, Data-JPA, Hibernate, MySQL, and a library to allow me to access JSP files. The index.jsp comes up but I almost feel like Spring Boot is giving me that free of charge as it's not even entering that method. I have been having the issue for a few days but trying to resolve it on my own - I found another answer that suggested to put a breakpoint inside one of the Spring classes but when I "debugged" it through Eclipse, it didn't even stop at that class - something about pattern matching - One answer suggested adding a context to the application.properties file - didn't help. I've reduced it to as simple as I think I can get it. Can anyone tell me what I might be doing wrong? Before my code, the project is on Github at: https://github.com/sfulmer/Scheduler.git
Here's my controller:
package net.draconia.schedule.controllers;
import java.util.List;
import net.draconia.schedule.beans.Event;
import net.draconia.schedule.dao.EventDAO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
#Controller
public class ScheduleController
{
private static final Logger logger = LoggerFactory.getLogger(ScheduleController.class);
#Autowired
private EventDAO mObjDAO;
protected EventDAO getDAO()
{
return(mObjDAO);
}
//#GetMapping("/events")
#RequestMapping(value = "events", method = RequestMethod.GET)
public #ResponseBody List<Event> getEvents()
{
logger.debug("I got here");
return(getDAO().getList());
}
#GetMapping("/")
public String index()
{
return("index");
}
}
Here is the DAO interface - I'll show the class if necessary but this is what the controller looks at:
package net.draconia.schedule.dao;
import java.util.List;
import javax.persistence.EntityNotFoundException;
import net.draconia.schedule.beans.Event;
public interface EventDAO
{
public Event getEventById(final long lId) throws EntityNotFoundException;
public List<Event> getList();
public void remove(final Event objEvent);
public void removeById(final long lId);
public Event save(final Event objEvent);
}
The Event class is so long but if I need to include it, I will. The application.properties file is here:
spring.datasource.url = jdbc:mysql://localhost:3306/schedule
spring.datasource.username = root
spring.datasource.password = R3g1n# M1lL$ 1$ My Qu3eN!
spring.mvc.view.prefix: /WEB-INF/jsp/
spring.mvc.view.suffix: .jsp
server.servlet.contextPath=/scheduler
and here is my Application class(with the SpringBootApplication annotation):
package net.draconia.schedule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
#SpringBootApplication(scanBasePackages = {"net.draconia.schedule.controller"})
public class ScheduleApp implements WebMvcConfigurer
{
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder)
{
return(builder.sources(ScheduleApp.class));
}
public static void main(String[] args)
{
SpringApplication.run(ScheduleApp.class, args);
}
}
I'm relatively new to Spring Boot but haven't ever ran into this problem ever before as I work with it at work and it works fine but we use entirely REST services there and I am using JSP files as well as sorta end-points that respond with JSON but you can't respond from REST services with JSP views so unfortunately I can't copy work's project to get that working or I would sigh Any thoughts on how I can get this working or what I am omitting?
My guess is that you're mixing things from Spring and Spring boot, and that's getting problems on loading beans, as you're probably changing the annotations load order or loading other beans rather than spring boot defaults as expected. For example, you implements WebMvcConfigurer, but you aren't providing any WebMvc Configuration, like a ViewResolver bean
My advice is to follow this guide: https://spring.io/guides/gs/spring-boot/
and use only the annotations from spring boot if using spring boot, or spring if using spring (they're similar, but not exactly the same, configuration is different).
Anyways, you can check loaded beans in Spring application context (Inject it in Application class) with ctx.getBeanDefinitionNames() method and see if your controller is there (i guess not).
By looking into code, my first impression is that, you have some typo in here:
#SpringBootApplication(scanBasePackages = {"net.draconia.schedule.controller"})
Your controller class package name has net.draconia.schedule.controllers.
So can you please correct your scanBasePackages with proper package name.
If that is not the case, please update full stack trace along with GET request which you are submitting into application. Will take a look & update answer accordingly.
This question already has answers here:
How can I #Autowire a spring bean that was created from an external jar?
(5 answers)
Closed 3 years ago.
I have a Spring Boot project and I can't get components from an external jar to be autowired. When I try to, I got a org.springframework.beans.factory.NoSuchBeanDefinitionException saying that can't find a bean with that name available.
I tried some solutions found in similar questions, like these ones:
How to autowire #service from external Jar in Spring
Spring Boot #autowired does not work, classes in different package
How can I #Autowire a spring bean that was created from an external jar?
..but still can't managed it to work.
Here is an example of what I'm trying to accomplish:
Here is boot class in the Spring Boot project spring-project-example
package com.springdi.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import com.dependency.example.DependencyBasePackageClass;
import com.dependency.example.somepackage.SomeBean;
#SpringBootApplication
#ComponentScan(basePackages = {"com.springdi.example"}, basePackageClasses = DependencyBasePackageClass.class)
public class SpringProjectExampleApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringProjectExampleApplication.class, args);
String beanName = SomeBean.class.getName();
System.out.printf("%s can be autowired: %s\n", beanName, String.valueOf(context.containsBean(beanName)).toUpperCase());
}
}
It's just a simple Spring Boot project checking if it is possible to autowire a component present in the dependency jar.
Here is the component in the jar (dependency-example-1.0.0.jar)
package com.dependency.example.somepackage;
import org.springframework.stereotype.Component;
#Component
public class SomeBean {
public void someMethod() {
System.out.println("Some process...");
}
}
And here is the base package class of this same jar
package com.dependency.example;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* Just a class to serve as the root for component
* scanning in "com.dependency.example" and its sub-packages
*/
#Configuration
#ComponentScan
public class DependencyBasePackageClass {
}
I've already tried #Import(DependencyBasePackageClass.class) in SpringProjectExampleApplication and #ComponentScan with basePackages and basePackageClasses, but no success.
I also tried using #SpringBootApplication(scanBasePackageClasses = {SpringProjectExampleApplication.class, DependencyBasePackageClass.class})
and the not type safe #SpringBootApplication(scanBasePackages = {"com.springdi.example", "com.dependency.example"}).
#Configuration #ComponentScan({"com.dependency.example"}) also fails, context.containsBean("com.dependency.example.somepackage.SomeBean") still returns false.
This jar is included in classpath and in the pom.xml as a dependency
<dependencies>
<!-- other dependencies -->
<dependency>
<groupId>com.rbaggio</groupId>
<artifactId>dependency-example</artifactId>
<version>1.0.0</version>
<scope>system</scope>
<systemPath>${basedir}/lib/dependency-example-1.0.0.jar</systemPath>
</dependency>
</dependencies>
Could it be the location of the jar, the way it is included or some extra configuration needed?
I'd appreciate any help! Thanks in advance.
Okey some basic things, you have mixed up your packages a bit.
#SpringBootApplication will scan all classes in packages below the class this is annotated on. This annotation is an alias for #EnableAutoConfiguration, #Configuration and #ComponentScan means that #ComponentScan(basePackages = {"com.springdi.example"}, basePackageClasses = DependencyBasePackageClass.class) is not needed.
com.springdi.example // class with #SpringBootApplication annotation
|
|
|
com.springdi.example.* // Will find all #Service, #Component, #Configuration
// in subpackages below the #SpringBootApplication
// annotation
You can read more about the annotation here SpringBootApplication
Since your other annotated classes are NOT in the same package structure as the #SpringBootApplication you need to define all the places you want to scan for annotations.
#SpringBootApplication(scanBasePackages = {"com.springdi.example", "com.dependency.example"})
will probably include all the packages that you want to scan through.
I am building a basic program of "hello world" in SpringBoot
Code
MyController.java
package controllers;
import org.springframework.stereotype.Controller;
#Controller
public class MyController {
public String hello() {
System.out.println("Hello World");
return "foo";
}
}
DemoApplication.java
package di.prac;
import java.util.Arrays;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import controllers.MyController;
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
ApplicationContext ctx=SpringApplication.run(DemoApplication.class, args);
MyController m = (MyController)ctx.getBean("myController");
m.hello();
System.out.println("*******"+Arrays.asList(ctx.getBeanDefinitionNames()));
}
}
I am using eclipse and created this project from http://start.spring.io/ without any dependencies.
I learned that Spring create the bean of MyController class with name myController ,but Spring is not able to find myController bean
ERROR
Exception in thread "main"
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
bean named 'myController' available at
org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:686)
at
org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1210)
at
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at
org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1089)
at di.prac.DemoApplication.main(DemoApplication.java:16)
Please find and explain the error in the Project
Place your controller under sub package of di.prac like di.prac.controllers or use #ComponentScan on your controller. By default, Spring scans the current and sub packages where your main application is present. If you want to scan other packages too, then you can specify the packages in #SpringBootApplication as an argument like.
#SpringBootApplication(scanBasePackages = {"com.xyz.controllers", "com.abc.models""})
We should avoid putting the #Configuration class in the default package (i.e. by not specifying the package at all). In this case, Spring scans all the classes in all jars in a classpath. That causes errors and the application probably doesn't start.
For your controller to be available in the context of Spring, you need to define that it is managed by the Spring container. Only the #Controller annotation is not enough, it indicates only the stereotype of your bean, as well as the annotations #Repository and #Service.
In cases where the beans have these annotations and are managed by Spring, it is because their packages that the spring is scanning to search for them has been specified programmatically or per xml. In your case, you should annotate your DemoApplication class with 2 other annotations:
#Configuration - Allows access to spring context
#ComponentScan - Packages to be scanned by Spring
#Configuration
#ComponentScan (basePackages = {"controllers"})
public class DemoApplication {
public static void main(String[] args) {
ApplicationContext ctx=SpringApplication.run(DemoApplication.class, args);
MyController m = (MyController)ctx.getBean("myController");
m.hello();
System.out.println(Arrays.asList(ctx.getBeanDefinitionNames()));
}
}
Just encountered same problem, solution is simple.You just (me also) created package "controllers" on the wrong place. It should be created not in java folder but under folder with name of your project. Simple but deadly mistake. Your code is written perfectly fine.
I am pretty new to Spring Boot Application. I wanted to understand how does a spring Boot Application create beans without #Configuration class . I had a look at a sample project where there was neither #Bean definitions nor a component scan yet #Autowired provided the dependency to the class. Please have a look at the snippet below:
#RestController
public class RestController{
**#Autowired
public CertificationService certificationService;**
.
.
.
.
}
//Interface
public interface CertificationService{
public List<Certification> findAll();
}
//Implementation Class
#Transactional
#Service
public class CertificationServiceImpl{
public List<Certification> findAll(){
.
.
}
}
My limited knowledge of springs tells me that when there is a #Service annotation over a class, there has to be a #ComponentScan somewhere to create the bean. But without a component scan, how does the CertificationServiceImpl bean gets created and thereby how does the autowiring of CertificationService in RestController works here?
As said in documentation:
... The #SpringBootApplication annotation is equivalent to using
#Configuration, #EnableAutoConfiguration and #ComponentScan...
Let say you have Spring Boot app class something like:
package com.mypackage;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class SpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootApplication.class, args);
}
}
Then all packages below of package com.mypackage will be scanned by default for Spring components. By the way, you can specify packages to scan right in #SpringBootApplication annotation, without usage of #ComponentScan. More details here.
How to create a Spring Java Web socket project with XML or Java Config but without Spring Boot. Where can I find a step-by-step tutorial. I dont know how to use spring boot in ecliplse. Also I dont want to use gradle or maven. I did not find a tutorial to use spring boot in eclipse. As I am new to spring I am unable to start a project without maven or gradle. I need to learn how to create a spring project without any built tool provided I need to use Eclipse. This is purly for learning puropse.
Below is the classes I used to replace Spring boot related main class
AppConfig Class
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
#Configuration
#ComponentScan("hello")
#EnableWebMvc
public class AppConfig {
}
WebAppInitializer Class
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration.Dynamic;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
public class WebAppInitializer implements WebApplicationInitializer{// extends AbstractAnnotationConfigDispatcherServletInitializer {
public void onStartup(ServletContext servletContext) throws ServletException
{
try
{
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(AppConfig.class);
ctx.setServletContext(servletContext);
Dynamic dynamic = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
dynamic.addMapping("/");
// dynamic.addMapping("/springStomp/");
dynamic.setLoadOnStartup(1);
//dynamic.setAsyncSupported(true);
//ctx.refresh();
System.out.println("config done");
}
catch(Exception e)
{
e.printStackTrace();
System.out.println("error");
}
}
}
WebSocketConfig Class
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
#Override
public void configureMessageBroker(MessageBrokerRegistry config) {
System.out.println("inside websocket config class");
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/hello").withSockJS();
}
}
Remaining is same as in spring web socket tutorial
I know how that feels, my company network is unfriendly towards my maven calls to download dependencies. If you had to do things the hard way like me goto www.mvnrepository.com and just type spring in the search and you can download the jars you need. If you encounter any NoClassDef errors during deployment or compilation it usually tells you what you are missing, then search for the keywords again in the link.
Just:
add gradle plugin in eclipse
import following project from spring site as gradle project
???
Profit!
Than if you don't want use spring boot remove any spring boot dependincies, add regular deps like spring-context, spring-webmvc, etc. And finally add spring-websocket and spring-messaging libraries.