I am creating a project that functions like an ecommerce website, and my base page http://localhost:8080 opens up, but if I try adding "/admin" or any of the other mappings in the controller class, I get the 404 Whitelabel page.
How can I make any of the other mappings appear properly?
I tried changing the #ComponentScan in the main class to
"#ComponentScan(basePackages = {"com.ecommerce.website.service.*", "com.ecommerce.website.controller.*", "com.ecommerce.website.repository.*" })"
but that did not solve the issue.
Main class
#SpringBootApplication
#EnableJpaRepositories("com.ecommerce.website.repository.*")
#ComponentScan("com.ecommerce.website.service.*")
#EntityScan("com.ecommerce.website.model.*")
public class EcommerceWebsiteApplication {
public static void main(String[] args) {
SpringApplication.run(EcommerceWebsiteApplication.class, args);
}
}
Controller class
package com.ecommerce.website.controller;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import com.ecommerce.website.model.Category;
import com.ecommerce.website.service.CategoryService;
//Category ID still having issues
//Need to add methods for Category delete and update methods
#Controller
public class AdminController {
//Injecting dependency
#Autowired
CategoryService categoryService;
//This method maps for /admin endpoint. It shows the adminHome.html page. The method is #GetMapping because you are getting information
//#return the adminHome page
#GetMapping("/admin")
public String adminHome() {
//Display html page
return "adminHome";
}
//This method maps for /admin/categories endpoint. It shows the categories.html page. The method is #GetMapping because you are getting information
//#return the categories page
#GetMapping("/admin/categories")
public String getCat(Model model) {
model.addAttribute("categories", categoryService.getAllCategories());
//Display html page
return "categories";
}
//This method maps for /admin/categories endpoint. It shows the categoriesAdd.html page, but before that, it creates
//a model that is sent to the html file via Thymeleaf. The categoriesAdd.html page is a form for adding a category
//The method is #GetMapping because you are getting information
//#param model will hold the category object so that the form can add information to it
//#return the categoriesAdd page
#GetMapping("/admin/categories/add")
public String getCatAdd(Model model) {
//Adding the model name "category", and creating a new Category object and putting it in the model
model.addAttribute("category", new Category());
//Display html page
return "categoriesAdd";
}
//This method maps for /admin/categories endpoint. It allows the user to add a category to the list of categories
//The method is #PostMapping because you are sending information
//#param category gets its value from the ModelAttribute, which gets its value from the form
//#return the categories page
#PostMapping("/admin/categories/add")
public String postCatAdd(#ModelAttribute("category") Category category) {
//Calling categoryService to add the category
categoryService.addCategory(category);
//Redirecting to page that shows all categories
return "redirect:/admin/categories";
}
Service
package com.ecommerce.website.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ecommerce.website.model.Category;
import com.ecommerce.website.repository.CategoryRepository;
#Service
public class CategoryService {
//Injecting dependency
#Autowired
CategoryRepository categoryRepository;
//This method calls categoryRepository to add a category to the database
//#param category is the category that is being added
public void addCategory(Category category) {
//Saving the category to the database
categoryRepository.save(category);
}
//This method calls categoryRepository to retrieve a list of categories
//#return the list of categories
public List<Category> getAllCategories() {
return categoryRepository.findAll();
}
}
Repository
package com.ecommerce.website.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.ecommerce.website.model.Category;
#Repository
public interface CategoryRepository extends JpaRepository<Category, Integer> {
}
POJO
package com.ecommerce.website.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Table;
import org.springframework.data.annotation.Id;
#Entity
#Table
public class Category {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "category_id")
private int id;
private String name;
public Category() {
}
public Category(int id, String name) {
super();
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
application.properties
spring.h2.console.enabled=true
spring.datasource.url=jdbc:h2:file:./db
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=update
server.port=8080
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.ecommerce</groupId>
<artifactId>ecommerce-website</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>ecommerce-website</name>
<description>Ecommerce website using Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-jpa -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-validation -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>1.0.2.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-security -->
<!--<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>3.0.0</version>
</dependency>-->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
EDIT
I removed all annotations from the main class, except for #SpringBootApplication and #ComponentScan, so now it looks like this:
#SpringBootApplication
#ComponentScan(basePackages={"com.ecommerce.website.service.*", "com.ecommerce.website.controller.*", "com.ecommerce.website.repository.*" })
public class EcommerceWebsiteApplication {
public static void main(String[] args) {
SpringApplication.run(EcommerceWebsiteApplication.class, args);
}
}
Currently what is being shown in my console
2022-12-27T22:43:35.202-06:00 INFO 5656 --- [ main] c.e.website.EcommerceWebsiteApplication : Starting EcommerceWebsiteApplication using Java 17.0.2 with PID 5656 (C:\Users\sohaib\eclipse-workspace\mongoDB-spring-boot\ecommerce-website-h2\target\classes started by sohaib in C:\Users\sohaib**strong text**\eclipse-workspace\mongoDB-spring-boot\ecommerce-website-h2)
2022-12-27T22:43:35.208-06:00 INFO 5656 --- [ main] c.e.website.EcommerceWebsiteApplication : No active profile set, falling back to 1 default profile: "default"
2022-12-27T22:43:36.611-06:00 INFO 5656 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2022-12-27T22:43:36.709-06:00 INFO 5656 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 87 ms. Found 1 JPA repository interfaces.
2022-12-27T22:43:37.831-06:00 INFO 5656 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2022-12-27T22:43:37.844-06:00 INFO 5656 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2022-12-27T22:43:37.844-06:00 INFO 5656 --- [ main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.1]
2022-12-27T22:43:37.989-06:00 INFO 5656 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2022-12-27T22:43:37.992-06:00 INFO 5656 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2658 ms
2022-12-27T22:43:38.033-06:00 INFO 5656 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2022-12-27T22:43:38.299-06:00 INFO 5656 --- [ main] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Added connection conn0: url=jdbc:h2:file:./db user=SA
2022-12-27T22:43:38.301-06:00 INFO 5656 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2022-12-27T22:43:38.314-06:00 INFO 5656 --- [ main] o.s.b.a.h2.H2ConsoleAutoConfiguration : H2 console available at '/h2-console'. Database available at 'jdbc:h2:file:./db'
2022-12-27T22:43:38.475-06:00 INFO 5656 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default]
2022-12-27T22:43:38.549-06:00 INFO 5656 --- [ main] org.hibernate.Version : HHH000412: Hibernate ORM core version 6.1.5.Final
2022-12-27T22:43:38.770-06:00 WARN 5656 --- [ main] org.hibernate.orm.deprecation : HHH90000021: Encountered deprecated setting [javax.persistence.sharedCache.mode], use [jakarta.persistence.sharedCache.mode] instead
2022-12-27T22:43:38.926-06:00 INFO 5656 --- [ main] SQL dialect : HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
2022-12-27T22:43:39.774-06:00 INFO 5656 --- [ main] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2022-12-27T22:43:39.782-06:00 INFO 5656 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2022-12-27T22:43:39.847-06:00 WARN 5656 --- [ main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2022-12-27T22:43:40.038-06:00 INFO 5656 --- [ main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index
2022-12-27T22:43:40.576-06:00 INFO 5656 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2022-12-27T22:43:40.587-06:00 INFO 5656 --- [ main] c.e.website.EcommerceWebsiteApplication : Started EcommerceWebsiteApplication in 5.879 seconds (process running for 6.41)
2022-12-27T22:47:31.683-06:00 INFO 5656 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2022-12-27T22:47:31.684-06:00 INFO 5656 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2022-12-27T22:47:31.685-06:00 INFO 5656 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 1 ms
Your controllers are simply not scanned by spring because you explicitly asked it to scan only the com.ecommerce.website.service.* package
However, your controllers are in com.ecommerce.website.controller.*
Why do you want to tell spring which scanner component?
Unless you have a good reason to do so, you should let it scan all the packages in your project.
Just put:
#SpringBootApplication
public class EcommerceWebsiteApplication {
public static void main(String[] args) {
SpringApplication.run(EcommerceWebsiteApplication.class, args);
}
}
More information on #ComponentScan : https://www.baeldung.com/spring-component-scanning
I'm new to the Spring framework and trying to create Spring-Boot combined with JSP to make a small web app. However, When I run the program, I get the following error.
Full stack trace:
2022-01-01 15:31:43.790 INFO 20116 --- [ restartedMain] spring.jsp.JspApplication : Starting JspApplication using Java 11.0.13 on cudayanh with PID 20116 (C:\Users\PC_1\Desktop\java_spring\spring-boot-jsp\jsp\target\classes started by PC_1 in C:\Users\PC_1\desktop\java_spring\spring-boot-jsp\jsp)
2022-01-01 15:31:43.791 INFO 20116 --- [ restartedMain] spring.jsp.JspApplication : No active profile set, falling back to default profiles: default
2022-01-01 15:31:43.916 INFO 20116 --- [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
2022-01-01 15:31:43.917 INFO 20116 --- [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
2022-01-01 15:31:47.098 INFO 20116 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2022-01-01 15:31:47.112 INFO 20116 --- [ restartedMain] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2022-01-01 15:31:47.112 INFO 20116 --- [ restartedMain] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.56]
2022-01-01 15:31:47.115 WARN 20116 --- [ restartedMain] o.a.catalina.core.AprLifecycleListener : This listener must only be nested within Server elements, but is in [TomcatEmbeddedContext].
2022-01-01 15:31:47.115 INFO 20116 --- [ restartedMain] o.a.catalina.core.AprLifecycleListener : Loaded Apache Tomcat Native library [1.2.31] using APR version [1.7.0].
2022-01-01 15:31:47.116 INFO 20116 --- [ restartedMain] o.a.catalina.core.AprLifecycleListener : APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true], UDS [true].
2022-01-01 15:31:47.116 INFO 20116 --- [ restartedMain] o.a.catalina.core.AprLifecycleListener : APR/OpenSSL configuration: useAprConnector [false], useOpenSSL [true]
2022-01-01 15:31:47.123 INFO 20116 --- [ restartedMain] o.a.catalina.core.AprLifecycleListener : OpenSSL successfully initialized [OpenSSL 1.1.1l 24 Aug 2021]
2022-01-01 15:31:47.499 INFO 20116 --- [ restartedMain] org.apache.jasper.servlet.TldScanner : At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
2022-01-01 15:31:47.515 INFO 20116 --- [ restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2022-01-01 15:31:47.515 INFO 20116 --- [ restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 3596 ms
2022-01-01 15:31:47.623 WARN 20116 --- [ restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'bookController' defined in file [C:\Users\PC_1\Desktop\java_spring\spring-boot-jsp\jsp\target\classes\spring\jsp\controllers\BookController.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'bookServiceImpl': Unsatisfied dependency expressed through field 'bookRepository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'spring.jsp.repositories.BookRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true), #org.springframework.beans.factory.annotation.Qualifier(value="spring.jsp.repositories.BookRepository")}
2022-01-01 15:31:47.626 INFO 20116 --- [ restartedMain] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
2022-01-01 15:31:47.653 INFO 20116 --- [ restartedMain] ConditionEvaluationReportLoggingListener :
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2022-01-01 15:31:47.713 ERROR 20116 --- [ restartedMain] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Field bookRepository in spring.jsp.services.impl.BookServiceImpl required a bean of type 'spring.jsp.repositories.BookRepository' that could not be found.
The following candidates were found but could not be injected:
- User-defined bean
- User-defined bean method 'provideBookRepository' in 'JspConfiguration'
Action:
Consider revisiting the entries above or defining a bean of type 'spring.jsp.repositories.BookRepository' in your configuration.
I've tried to fix this by referring and using a bunch of solutions, other people provided out there like adding #Service, #Repository to the implementation class. However, none of them worked.
repositories/BookRepository.java
public interface BookRepository {
Collection<Book> findAll();
Optional<Book> findById(String isbn);
Book add(Book book);
}
repositories/impl/InMemoBookRepositoryImpl.java
#Service
#Primary
public class InMemoBookRepositoryImpl implements BookRepository {
#Autowired
private final Map<String, Book> booksStore;
public InMemoBookRepositoryImpl(Map<String, Book> booksStore) {
this.booksStore = booksStore;
this.booksStore.putAll(booksStore);
}
#Override
public Collection<Book> findAll() {
if (this.booksStore.isEmpty()) {
return Collections.emptyList();
}
return booksStore.values();
}
#Override
public Optional<Book> findById(String isbn) {
return Optional.ofNullable(booksStore.get(isbn));
}
#Override
public Book add(Book book) {
booksStore.put(book.getIsbn(), book);
return book;
}
}
services/BookService.java
public interface BookService {
Collection<BookDTO> getBooks();
BookDTO addBook(BookDTO book);
}
services/impl/BookServiceImpl.java
#Service
#Primary
public class BookServiceImpl implements BookService {
#Autowired
#Qualifier("spring.jsp.repositories.BookRepository")
private final BookRepository bookRepository;
public BookServiceImpl(BookRepository bookRepository) {
this.bookRepository = bookRepository;
}
#Override
public Collection<BookDTO> getBooks() {
return bookRepository.findAll()
.stream()
.map(BookServiceImpl::convertBookDto)
.collect(Collectors.toList());
}
#Override
public BookDTO addBook(BookDTO bookDto) {
final Optional<Book> existingBook = bookRepository.findById(bookDto.getIsbn());
if (existingBook.isPresent()) {
throw new DuplicateBookException(bookDto);
}
final Book savedBook = bookRepository.add(convertToBook(bookDto));
return convertBookDto(savedBook);
}
private static BookDTO convertBookDto(Book book) {
return new BookDTO(book.getIsbn(), book.getName(), book.getAuthor());
}
private static Book convertToBook(BookDTO bookDto) {
return new Book(bookDto.getIsbn(), bookDto.getName(), bookDto.getAuthor());
}
}
controllers/BookController.java
#Controller
#RequestMapping("/book")
public class BookController {
#Autowired
#Qualifier("spring.jsp.services.bookService")
private final BookService bookService;
public BookController(BookService bookService) {
this.bookService = bookService;
}
#GetMapping("/books")
public String getBooks(Model model) {
model.addAttribute("books", this.bookService.getBooks());
return "booksList";
}
#GetMapping("/addBook")
public String addBook(Model model) {
model.addAttribute("book", new Book());
return "addBook";
}
#PostMapping("/addBook")
public RedirectView addBook(#ModelAttribute("book") BookDTO bookDto, RedirectAttributes redirectAttributes) {
final RedirectView redirectView = new RedirectView("/book/addBook", true);
BookDTO savedBook = bookService.addBook(bookDto);
redirectAttributes.addFlashAttribute("savedBook", savedBook);
redirectAttributes.addFlashAttribute("addBookSuccess", true);
return redirectView;
}
}
The main method
#SpringBootApplication(scanBasePackages = "spring.jsp")
#EntityScan("spring.jsp")
#ComponentScan({ "spring.jsp" })
public class JspApplication extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(JspApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(JspApplication.class, args);
}
}
And finally, the pom.xml configuration
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- <packaging>war</packaging> -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>spring</groupId>
<artifactId>jsp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>jsp</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- specifies the Tomcat JSP dependency(jsp parser) -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<!-- -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<scope>provided</scope>
</dependency>
<!-- JSTL tag lib -->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>javax.servlet.jsp.jstl-api</artifactId>
<version>1.2.1</version>
</dependency>
<!-- running in a Tomcat web container. -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>2.4.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.8.4</version>
<configuration>
<testFailureIgnore>true</testFailureIgnore>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
Try simplifying your main class and rely on the annotations defaults as follows:
#SpringBootApplication
#EntityScan("spring.jsp")
public class JspApplication extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(JspApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(JspApplication.class, args);
}
}
#SpringBootApplication encapsulates #Configuration, #EnableAutoConfiguration, and #ComponentScan annotations with their default attributes. The default value for #ComponentScan means that all the sub packages on the package the #ComponentScan is used are scanned. That is why it is usually a good practice to include the main class in the base package of the project.
Try running mvn clean package and restart the spring application from your IDE afterwards.
I had the same issue and this solved it.
I am trying to configure my Spring Boot application to use Keycloak as SSO.
I am following standard tutorials in this topic:
First add dependency
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-boot-starter</artifactId>
</dependency>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.keycloak.bom</groupId>
<artifactId>keycloak-adapter-bom</artifactId>
<version>13.0.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Second, fill properties
# Keycloak
keycloak.realm = Mixeway
keycloak.auth-server-url = http://localhost:8180/auth
keycloak.ssl-required = external
keycloak.resource = MixewayApp
keycloak.credentials.secret = secret
keycloak.use-resource-role-mappings = false
keycloak.bearer-only = false
keycloak.security-constraints[0].authRoles[0]=USER
keycloak.security-constraints[0].securityCollections[0].patterns[0]=/v2/auth/keycloak
Third create controller to handle authentication
#GetMapping(value = "/v2/auth/keycloak")
public void authUsingKeycloak(Principal principal){
log.info("user {} logged using keycloak", principal.getName());
}
Authentication works properly. I can see logs:
2021-12-30 10:18:48.213 DEBUG 6947 --- [nio-8443-exec-3] o.k.adapters.OAuthRequestAuthenticator : Verifying tokens
2021-12-30 10:18:48.265 DEBUG 6947 --- [nio-8443-exec-3] o.k.a.rotation.JWKPublicKeyLocator : Realm public keys successfully retrieved for client MixewayApp. New kids: [mpkD1RwCaaIbp8tN-a9__hlc03UpxrQ8SE5atlDrF78]
2021-12-30 10:18:48.270 DEBUG 6947 --- [nio-8443-exec-3] o.k.adapters.OAuthRequestAuthenticator : Token Verification succeeded!
2021-12-30 10:18:48.277 DEBUG 6947 --- [nio-8443-exec-3] o.k.a.rotation.JWKPublicKeyLocator : Realm public keys successfully retrieved for client MixewayApp. New kids: [mpkD1RwCaaIbp8tN-a9__hlc03UpxrQ8SE5atlDrF78]
2021-12-30 10:18:48.277 DEBUG 6947 --- [nio-8443-exec-3] o.k.adapters.OAuthRequestAuthenticator : successful authenticated
2021-12-30 10:18:48.283 DEBUG 6947 --- [nio-8443-exec-3] o.k.adapters.RequestAuthenticator : User '343050ef-bc48-48ae-af93-5dd3f0830956' invoking 'https://localhost:8443/v2/auth/keycloak?state=d1ebaf04-c0fd-4415-8f70-56b68e9f8485&session_state=e2e280a0-428d-4481-99c6-f45cfa171f4c&code=da46d2ee-14b5-45ef-a15f-6a69e196f092.e2e280a0-428d-4481-99c6-f45cfa171f4c.0b00edfd-1474-42ec-a2df-f2754b830dc6' on client 'MixewayApp'
2021-12-30 10:18:48.283 DEBUG 6947 --- [nio-8443-exec-3] o.k.adapters.RequestAuthenticator : AUTHENTICATED
2021-12-30 10:18:48.291 DEBUG 6947 --- [nio-8443-exec-4] o.k.adapters.PreAuthActionsHandler : adminRequest https://localhost:8443/v2/auth/keycloak
2021-12-30 10:18:48.291 DEBUG 6947 --- [nio-8443-exec-4] o.k.adapters.RequestAuthenticator : AUTHENTICATED: was cached
2021-12-30 10:18:48.291 DEBUG 6947 --- [nio-8443-exec-4] .k.a.t.AbstractAuthenticatedActionsValve : AuthenticatedActionsValve.invoke /v2/auth/keycloak
However I am getting NullPointer Exception due to null Principal object. Can anyone give me a hint how to configure keycloak auth in spring so that principal object is set properly?
EDIT
after rewriting controller to
#GetMapping(value = "/v2/auth/keycloak")
public void authUsingKeycloakGet(HttpServletRequest request){
KeycloakPrincipal principal=(KeycloakPrincipal) request.getUserPrincipal();
KeycloakSecurityContext session = principal.getKeycloakSecurityContext();
AccessToken accessToken = session.getToken();
}
and debugging application I am able to see principal in HttpServletRequest but both principal and request.getUserPrincipal() is still null:
As it is in controller level and you are creating an endPoint, you need to use #RequestBody annotation for the body inputs, #RequestParam annotation for request parameters (i.e. yourEndPoint?id=1) or #PathVariable for path variables in the endPoint (i.e. yourEndPoint/1).
Spring boot actuator is already included in the POM, and it shows in the startup logs.
However, when I try to access /actuator or even the base url of my project, I get the following -
{
"timestamp": 1577096144986,
"status": 401,
"error": "Unauthorized",
"message": "Full authentication is required to access this resource",
"path": "/actuator"
}
I read that there could be basic HTTP authentication set for the end points.
I looked for spring.security.user.name, password in the config properties, but could not find any.
If I hit http://localhost:8083/actuator, or even http://localhost:8083/ or any URL other the mapped API end points, it seems, I get this password prompt on browser -
On application logs, I get this -
2019-12-23 19:30:54,489 75773 [XNIO-3 task-3] INFO c.c.common.web.LoggerInterceptor [LoggerInterceptor.java:42] - Visitor [okp91Dj1NzT2KPPUjaUvhqEg4oOhwPQ49I9LTR2z] [GET] [/error] [1ms] [OK]
2019-12-23 19:30:54,493 75777 [XNIO-3 task-3] ERROR org.apache.velocity [CommonsLogLogChute.java:96] - ResourceManager : unable to find resource 'error.vm' in any resource loader.
On entering credentials, it fails and the password prompt appears again, with the same logs as above repeated.
Updates
Spring boot version - 1.5.2.RELEASE.
There is a web.xml inside /src/main/resources. It has following -
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:META-INF/spring/applicationContext*.xml
classpath*:com.packagename
/WEB-INF/spring/oauth-security.xml
/WEB-INF/spring/security-config.xml
classpath*:META-INF/gateway/*.xml
</param-value>
</context-param>
I could locate the oauth-security.xml and security.xml files in this microservice component.
oauth-security.xml has oauth scopes based definitions for API paths -
<sec:http pattern="/service/v2/**"
create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint"
access-decision-manager-ref="accessDecisionManager">
<sec:intercept-url pattern="/some/path/v2/profile/**" access="ROLE_USER,SCOPE_PROFILE" method="GET"/>
I see security-config.xml which imports webmvc-config.xml.
I see some of these in security-config.xml -
<sec:http pattern="/somepath/**">
<sec:intercept-url pattern="/somepath/**" access="ROLE_USER"/>
<sec:http-basic/>
</sec:http>
but I don't see any configurations for /** paths anywhere.
Update 2
I checked that there seem to be auth configurations in a file called customscopes.properties as well, which seems to be a custom file, added to webmvc-config.xml like this -
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<value>classpath:/spring/application.properties</value>
<value>classpath:/spring/local.properties</value>
<value>classpath:/spring/customscopes.properties</value>
<value> file:${project.config.dir}/application.properties </value>
<value>file:${project.config.dir}/customscopes.properties</value>
</list>
</property>
</bean>
customscopes.properties has urls like these -
service/v2/path/**=SCOPE_SOMETHING;
At the same, time, there is the same url in oauth-security.xml -
<sec:intercept-url pattern="/service/v2/path/**" access="SCOPE_SOMETHING"/>
I am not sure why there are two sets of configs. I tried changing those one by one, while keeping the other with authentication. I observed that only changing the customscopes.properties affected -
service/v2/path/**=IS_AUTHENTICATED_ANONYMOUSLY;
I am new to Spring Security as well. I checked this video tutorial but could not find those mentioned config methods in my project. There is no mention of WebSecurityConfigurerAdapter.
However, adding the path for actuator/** on both these files, with IS_AUTHENTICATED_ANONYMOUSLY did not work - 401 error as shown in the beginning.
Update 3
Oh, another thing - security-config.xml contains
<sec:http pattern="/favicon.ico" security="none"/>
And I see a difference in the logs when I access http://localhost:8083/actuator/ and http://localhost:8083/somethingelse/
http://localhost:8083/actuator/
Step 1 - Hit this url - log -
2019-12-24 12:31:03,051 590999 [XNIO-3 task-16] INFO c.c.common.web.LoggerInterceptor [LoggerInterceptor.java:42] - Visitor [OICBz6CqYzI58UqobnBYNEXsZUNErjBkv6wEUUkX] [GET] [/error] [2ms] [OK]
2019-12-24 12:31:03,054 591002 [XNIO-3 task-16] ERROR org.apache.velocity [CommonsLogLogChute.java:96] - ResourceManager : unable to find resource 'error.vm' in any resource loader.
Step 2 - cancel sign in form - get favicon.ico instead of /error -
2019-12-24 12:31:18,641 606589 [XNIO-3 task-20] ERROR org.apache.velocity [CommonsLogLogChute.java:96] - ResourceManager : unable to find resource 'error.vm' in any resource loader.
2019-12-24 12:31:18,912 606860 [XNIO-3 task-21] INFO c.c.common.web.LoggerInterceptor [LoggerInterceptor.java:42] - Visitor [OICBz6CqYzI58UqobnBYNEXsZUNErjBkv6wEUUkX] [GET] [/favicon.ico] [2ms] [OK]
http://localhost:8083/somethingelse
Step 1 - Hit this url - log -
2019-12-24 12:31:03,051 590999 [XNIO-3 task-16] INFO c.c.common.web.LoggerInterceptor [LoggerInterceptor.java:42] - Visitor [OICBz6CqYzI58UqobnBYNEXsZUNErjBkv6wEUUkX] [GET] [/error] [2ms] [OK]
2019-12-24 12:31:03,054 591002 [XNIO-3 task-16] ERROR org.apache.velocity [CommonsLogLogChute.java:96] - ResourceManager : unable to find resource 'error.vm' in any resource loader.
Step 2 - cancel sign in form - Same log as above, again
Update 4
If I add a class to extend WebSecurityConfigurerAdapter, and just add a permitAll() against my required paths -
#Override
protected void configure(HttpSecurity http) throws Exception {
http.
authorizeRequests().antMatchers("/service/trace/**").permitAll()
.antMatchers("/service/actuator/**").permitAll()
.antMatchers("/actuator/**").permitAll()
.antMatchers("/trace").permitAll()
.antMatchers("/actuator").permitAll();
}
I get different errors this time (404 Not found) -
{
"timestamp": 1577181851520,
"status": 404,
"error": "Not Found",
"message": "Not Found",
"path": "/service/trace"
}
Note - I have a doubt about which are the available actuator end points, so I am trying to ensure for all these combinations. See the application startup logs below if you can confirm on the basis of that.
I get 404 errors against all these URLs -
http://localhost:8083/service/actuator/beans
http://localhost:8083/actuator/beans
http://localhost:8083/beans
And my other authenticated API endpoints start giving this error -
{
"timestamp": 1577181062281,
"status": 403,
"error": "Forbidden",
"message": "Could not verify the provided CSRF token because your session was not found.",
"path": "/service/v2/some/end/point"
}
ALso, I found that we have these filters as well defined in the web.xml. So, it seems there is Spring configuration, as well as Spring boot addition. Correct me if my understanding is wrong.
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
So, the problem comes down to this -
I can't access the actuator end points. I see the following in application startup logs, containing actuator, but I can't seem to load them either. I guess Spring security is coming in between but not able to prevent the same.
2019-12-24 14:14:10,769 14209 [main] INFO o.s.b.a.e.m.EndpointHandlerMapping [AbstractHandlerMethodMapping.java:543] - Mapped "{[/beans || /beans.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2019-12-24 14:14:10,770 14210 [main] INFO o.s.b.a.e.m.EndpointHandlerMapping [AbstractHandlerMethodMapping.java:543] - Mapped "{[/health || /health.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint.invoke(javax.servlet.http.HttpServletRequest,java.security.Principal)
2019-12-24 14:14:10,771 14211 [main] INFO o.s.b.a.e.m.EndpointHandlerMapping [AbstractHandlerMethodMapping.java:543] - Mapped "{[/autoconfig || /autoconfig.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2019-12-24 14:14:10,772 14212 [main] INFO o.s.b.a.e.m.EndpointHandlerMapping [AbstractHandlerMethodMapping.java:543] - Mapped "{[/metrics/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.MetricsMvcEndpoint.value(java.lang.String)
2019-12-24 14:14:10,772 14212 [main] INFO o.s.b.a.e.m.EndpointHandlerMapping [AbstractHandlerMethodMapping.java:543] - Mapped "{[/metrics || /metrics.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
Note -
I have added management.endpoints.web.exposure.include=* in application.properties
I can't see anything like this -
2019-12-24 15:57:41.245 INFO 37683 --- [ main] o.s.b.a.e.web.EndpointLinksResolver : Exposing 18 endpoint(s) beneath base path '/actuator'
spring-boot-starter-actuator-1.5.2.RELEASE.jar is there in External libraries of Intellij.
I have faced the similar error and added this configuration in application.properties :
management.endpoints.web.base-path=/
This would allow you to access all the actuator endpoints.
The error occurs as security is not enabled on the endpoint.
For a locally deployed app, add the following configuration to your application.properties file -
management.security.enabled=false
On a production app, more careful configurations would need to be made.
1)I tested the code with spring boot 1.5.2 and discovered that in this version the actuator endpoints are available in the root('/') path and not at /actuator path.
Your logs confirm it also:
2019-12-24 14:14:10,769 14209 [main] INFO o.s.b.a.e.m.EndpointHandlerMapping [AbstractHandlerMethodMapping.java:543] - Mapped "{[/beans || /beans.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
As you see in log, endpoint for example for beans is /beans. In your case http://localhost:8083/beans
In addition you need also as Prerak Jain wrote following:
management.security.enabled=false
2)
To your problem with HTTP 403:
{
"timestamp": 1577181062281,
"status": 403,
"error": "Forbidden",
"message": "Could not verify the provided CSRF token because your session was not found.",
"path": "/service/v2/some/end/point"
}
To fix it you need to add following to your configuration
"and().csrf().disable()", so for example:
http.authorizeRequests().antMatchers("/service/trace/**").permitAll().and().csrf().disable()
That disables csrf token stuff.
Dealing with Legacy application is never easy. Indeed, it seems like you are mixing Spring and Spring-boot configuration altogether. I suggest you to proces step by step. Go back to a working, stable state and then move on:
Make sure you are using the right dependencies
I've been doing some tests with spring-boot-starter-actuator with spring-boot-starter-parent.
Here is the content of my pom.xml:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
Please notice that spring-boot-starter-actuator:2.2.2.RELEASE works in different ways that spring-boot-starter-actuator:1.5.2.RELEASE, mostly regarding the security.
Also note that we use the starterof every dependency. If not, you won't all spring boot autoconfiguration enabled.
Configure properly spring-boot-starter-actuator
In your application.properties, add the following lines :
# Make sure every actuator endpoints are located under the same root URL
management.context-path=/actuator
# Disable default actuator security rules to manage everything with your Java configuration
management.security.enabled=false
Try to manage only the access to /actuator
In your java configuration class, the one that extends WebSecurityConfigurerAdapter, apply the following changes:
#EnableWebSecurity // Enable spring security configuration
#Configuration // Is a Spring Configuration class
#Order(ManagementServerProperties.ACCESS_OVERRIDE_ORDER) // To override the default actuator security configuration
public class WebSecurity extends WebSecurityConfigurerAdapter {
/**
* We try to make sure you can easily manage spring actuator endpoints
*/
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.mvcMatchers("/actuator/**").authenticated() // To restrict access to authenticated user on actuator endpoints
.anyRequest().permitAll()
.and()
.csrf().disable(); // If you want to POST data, you have to disable CSRF check. Otherwise, you always get an error when POSTing data on an unsecured URL.
}
}
For more information about CSRF, please check: https://fr.wikipedia.org/wiki/Cross-site_request_forgery
In the console, you're supposed to see something like this during the server start up:
019-12-30 12:13:34.767 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/beans || /actuator/beans.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2019-12-30 12:13:34.768 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/trace || /actuator/trace.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2019-12-30 12:13:34.769 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/configprops || /actuator/configprops.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2019-12-30 12:13:34.773 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/metrics/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.MetricsMvcEndpoint.value(java.lang.String)
2019-12-30 12:13:34.773 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/metrics || /actuator/metrics.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2019-12-30 12:13:34.774 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/autoconfig || /actuator/autoconfig.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2019-12-30 12:13:34.775 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/health || /actuator/health.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint.invoke(javax.servlet.http.HttpServletRequest,java.security.Principal)
2019-12-30 12:13:34.776 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/dump || /actuator/dump.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2019-12-30 12:13:34.778 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/heapdump || /actuator/heapdump.json],methods=[GET],produces=[application/octet-stream]}" onto public void org.springframework.boot.actuate.endpoint.mvc.HeapdumpMvcEndpoint.invoke(boolean,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.io.IOException,javax.servlet.ServletException
2019-12-30 12:13:34.779 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/mappings || /actuator/mappings.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2019-12-30 12:13:34.782 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/loggers/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.LoggersMvcEndpoint.get(java.lang.String)
2019-12-30 12:13:34.783 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/loggers/{name:.*}],methods=[POST],consumes=[application/vnd.spring-boot.actuator.v1+json || application/json],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.LoggersMvcEndpoint.set(java.lang.String,java.util.Map<java.lang.String, java.lang.String>)
2019-12-30 12:13:34.784 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/loggers || /actuator/loggers.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2019-12-30 12:13:34.785 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/auditevents || /actuator/auditevents.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public org.springframework.http.ResponseEntity<?> org.springframework.boot.actuate.endpoint.mvc.AuditEventsMvcEndpoint.findByPrincipalAndAfterAndType(java.lang.String,java.util.Date,java.lang.String)
2019-12-30 12:13:34.786 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/info || /actuator/info.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2019-12-30 12:13:34.788 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/env/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EnvironmentMvcEndpoint.value(java.lang.String)
2019-12-30 12:13:34.789 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/env || /actuator/env.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
Let me know if you have any difficulties, or you're console is printing different output.
Please also share your pom.xml if any of this works.
One way of running the actuator is assigning a different port to the actuator service
this could be done by adding following property to application.properties
management.server.port=8084
This way you can run and access actuator on a different port and can create rules on the gateway as to how it can be accessed.
Click here for detail
Another way is to disable security from actuator to add following property to the application.properties
management.endpoints.web.exposure.include=*
Click here for detail
Another way of bypassing all the security is following
#Configuration(proxyBeanMethods = false)
public class ActuatorSecurity extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeRequests((requests) ->
requests.anyRequest().permitAll());
}
}
Click here for detail
Hope it helps.
I am new to Spring boot ( and servlet 3.0 ). I am trying to create spring mvc project with JSP as view. When I return a view from my controller it is not getting resolved as JstlView.
Here is what I did:
#SpringBootApplication
public class MyApp extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(MyApp.class, args);
}
}
#Controller
public class MainController {
#RequestMapping( value="/main" , method = RequestMethod.GET )
public String main(){
return "main";
}
#RequestMapping( value="/" , method = RequestMethod.GET )
public String welcome(){
return "welcome";
}
}
Created both .jsp files in src\main\webapp\WEB-INF\jsp .
After googling I found that I need to specify this in application.properties So I added following in props:
spring.mvc.view.prefix: /WEB-INF/jsp/
spring.mvc.view.suffix: .jsp
logging.level.org.springframework: TRACE
logging.level.com: TRACE
Even after this it is not working. Here is the trace.
2016-04-24 19:54:49.016 TRACE 7880 --- [nio-8080-exec-1] .w.s.m.m.a.ServletInvocableHandlerMethod : Invoking [MainController.welcome] method with arguments []
2016-04-24 19:54:49.016 TRACE 7880 --- [nio-8080-exec-1] .w.s.m.m.a.ServletInvocableHandlerMethod : Method [welcome] returned [welcome]
2016-04-24 19:54:49.020 DEBUG 7880 --- [nio-8080-exec-1] o.s.w.s.v.ContentNegotiatingViewResolver : Requested media types are [text/html, application/xhtml+xml, image/webp, application/xml;q=0.9, */*;q=0.8] based on Accept header types and producible media types [*/*])
2016-04-24 19:54:49.020 DEBUG 7880 --- [nio-8080-exec-1] o.s.w.servlet.view.BeanNameViewResolver : No matching bean found for view name 'welcome'
2016-04-24 19:54:49.022 DEBUG 7880 --- [nio-8080-exec-1] o.s.b.f.s.DefaultListableBeanFactory : Invoking afterPropertiesSet() on bean with name 'welcome'
2016-04-24 19:54:49.022 TRACE 7880 --- [nio-8080-exec-1] o.s.w.s.v.InternalResourceViewResolver : Cached view [welcome]
2016-04-24 19:54:49.022 DEBUG 7880 --- [nio-8080-exec-1] o.s.w.s.v.ContentNegotiatingViewResolver : Returning [org.springframework.web.servlet.view.InternalResourceView: name 'welcome'; URL [/WEB-INF/jsp/welcome.jsp]] based on requested media type 'text/html'
2016-04-24 19:54:49.022 DEBUG 7880 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Rendering view [org.springframework.web.servlet.view.InternalResourceView: name 'welcome'; URL [/WEB-INF/jsp/welcome.jsp]] in DispatcherServlet with name 'dispatcherServlet'
2016-04-24 19:54:49.022 TRACE 7880 --- [nio-8080-exec-1] o.s.w.servlet.view.InternalResourceView : Rendering view with name 'welcome' with model {} and static attributes {}
2016-04-24 19:54:49.026 DEBUG 7880 --- [nio-8080-exec-1] o.s.w.servlet.view.InternalResourceView : Forwarding to resource [/WEB-INF/jsp/welcome.jsp] in InternalResourceView 'welcome'
2
As you see in the trace, this is trying to resolve /jsp/welcome.jsp as InternalResourceView instead of JstlView. Eventually it fails as 404.
What other steps I need to follow? Is there any tutorial for SpringBoot-mvc with jsp ?
P.S. I can create spring mvc app with jsp using web.xml ( using JstlView in my config file ). But I can't find any tutorial for Spring boot mvc with jsp.
#Bean
public ViewResolver getViewResolver(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/jsp/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
return resolver;
}
also needed and your pages should be at /webapp/WEB-INF/jsp/
+
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
Assuming it is embedded Tomcat,
You need to have followings in your pom.xml
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
Embedded Tomcat core package has no JSP rendering support.
You do not require the ViewResolver. pom.xml needs the mentioned dependencies as told by Yura and place the jsp files in src\main\webapp\WEB-INF\jsp.
If we want to use jsp as view in spring boot(which by default has tomcat server) we need to add the following to our pom.xml:
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
we need to add our pages inside
src/main/webapp/WEB-INF/view
After this we can specify the location for our jsp pages in application.properties
spring.mvc.view.prefix=/WEB-INF/view/
spring.mvc.view.suffix=.jsp
Create webapp/WEB-INF/views {Name the last folder as U Like }
under src/main
add jstl jar
add following two lines in application.properties
spring.mvc.view.prefix:/WEB-INF/views/
spring.mvc.view.suffix:.jsp
Run As Spring Boot App ..U are good to go !
For More U can consult my this project on github :
https://github.com/SudipBiswasRana/Using-JSP-As-View-For-Spring-Project