Spring App won't work with JSP - java

I am new to Spring Framework. Trying to make a Java based Spring MVC project. Here is my main application class
#SpringBootApplication
#ComponentScan
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
#Controller
public class HelloController {
#RequestMapping("/")
public String hello(){
return "hello";
}
}
When I run the project I get the error
There was an unexpected error (type=Not Found, status=404).
No message available
Why Spring can not display JSP files?

Add following to application.properties
spring.mvc.view.prefix: /WEB-INF/jsp/
spring.mvc.view.suffix: .jsp
Edit :You can refer sample project here
Below step is not required, but worth a try.
As per another post, you need following dependencies
<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>

Related

Jax-rs annotation Path is not work in java spring boot?

I have spring boot application with starter version 2.1.16, and spring-boot-starter-web dependency. So, i want use javax.ws.rs-api library, and add dependency:
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.1.1</version>
</dependency>
So when i create controller, and add #Path, #Get - i don't get answer from the server (404 not found). How makes it work?
package com.example.test;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.ext.Provider;
#RestController
public class MyController {
//Doesn't work (404 not found
#GET
#Path("/my_test")
public String check() {
return "hi!";
}
//Work
#RequestMapping("/my_test2")
public String check2() {
return "hi2!";
}
}
Add the following dependency in your pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
</dependencies>
if you use spring boot starter version 2.1.16, you will normally have a parent pom which will also define the default version for the above dependency.
Then replace #RestController with #Path("/") from package javax.ws.rs.Path
Now it should be working.
Keep in mind your embedded server now, will be jersey instead of default tomcat.
Edit: Also as found from the author of the question another change is needed to register a ResourceConfig. This is also described here in the official documentation.
In addition to the post above, you need to add the config class:
#Configuration
public class JerseyConfig {
#Bean
public ResourceConfig resourceConfig(MyController myController) {
ResourceConfig config = new ResourceConfig();
config.register(myController);
return config;
}
}

SpringBoot Web MVC Application cannot resolve JSP views

I am trying to implement a web application using Springboot. but when I request methods I get 404 Error. Springboot cannot find Jsp files.
this is my Controller Code:
#PostMapping(value = "/loginSuccess")
public ModelAndView loginSuccess() {
System.out.println("in login success");
return new ModelAndView("index");
}
#GetMapping(value = "/loginError")
public ModelAndView showLoginError() {
System.out.println("in login error");
return new ModelAndView("error");
}
and this is my SecurityConfig:
#ComponentScan
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private EmployeeRepository employeeRepository;
#Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
#Bean
public UserDetailsService userDetailsService(){
return new EmployeeDetailService(employeeRepository, passwordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.formLogin()
.successForwardUrl("/loginSuccess")
.failureUrl("/loginError")
.permitAll()
.and()
.authorizeRequests()
.antMatchers("/").permitAll()
.and()
.httpBasic();
}
}
I also specified prefix and suffix in application.properties:
spring.mvc.view.prefix=/static/
spring.mvc.view.suffix=.jsp
I also have these dependencies in my pom file:
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
and this is my Project Structure:
can anyone tell me what is the problem?
The main template engines for SpringBoot are Thymeleaf, Groovy, FreeMarker, Jade. In the reference guide:
JSP should be avoided if possible, there are several known limitations
when using them with embedded servlet containers.
An executable jar will not work because of a hard coded file pattern
in Tomcat.
If the JSPs are legacy or proprietary codes that you can't convert, you have to do a few things in order to develop/maintain, compile and kinda run a SpringBootApplication running them in Intellij:
maven: your pom must be a 'war' package.
That will makes intellij look for and compile the JSPs right.
web facet: put your .jsp files in a folder where they are expected to be in a webapp: src/main/webapp/WEB-INF/jsp/
The jsp will never be 'compiled'/'interpretable' in static.
spring facet: set the prefix to /WEB-INF/jsp/ in your application.properties
tomcat: have those dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<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>
build runnable war: make an Intellij "maven configuration" that run :
clean install -f pom.xml
run that war: make an Intellij "jar configuration" with those settings:
path to jar : <the path to the war file in the target folder>
before launch : run the "maven configuration" you created
i had a similar problem and for me specifying the web resource directory containing the JSP files resolved the issue.
open project structure and under modules -> web -> web resource directory specify the directory in which your view are contained (in this case webapp)
open application.properties
specify the folder within your webresource directory which contains your views as prefix (in this case /views/)
specify your view suffix .jsp
this should enable intelij to resolve the views returned by the controller.

Test class in spring dosn't work properly

I would like to test my controller class. But I couldn't manage to run springBootTest class. My project written in spring boot. We are writing REST API using spring boot.
When I try to excute following test class. I still get following line from terminal.
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.context.SpringBootTest;
import static org.assertj.core.api.Assertions.assertThat;
/*
*
* #A Sabirov Jakhongir
*
*/
#SpringBootTest
#WebMvcTest
public class PrivilegesControllerTest {
#Autowired
private PrivilegesController privilegesController;
#Test
public void add() {
assertThat(privilegesController).isNotNull();
}
}
I put here all needed dependency for testing from my project.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.platform/junit-platform-launcher -->
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<version>1.6.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.3.2</version>
<scope>test</scope>
</dependency>
What might be cause of not working of test Class.
With Junit5 and #SpringBootTest will load the full application, I had faced the same issue before, you can find details about the question here and answer here.
The solution for this is to use your test without #SpringBootTest.
The solution to your test class is as below.
#ExtendWith(MockitoExtension.class)
public class PrivilegesControllerTest {
#InjectMocks
private PrivilegesController privilegesController;
#Test
public void add() {
assertThat(privilegesController).isNotNull();
}
}
You can also use #ExtendWith(SpringExtension.class) instead of #ExtendWith(MockitoExtension.class)
To test spring boot application is creating your controller, use #SpringBootTest annotation, and to test the behavior or responsibility of the controller is better to use #WebMvcTest. No need to annotate both the annotation to one class.
There are two cases to test the controller's responsibility.
With running Server
Without Server
For 1st Case, you can use #SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) to start a server with a random port.
For 2nd Case, use #WebMvcTest for testing the web layer.
All the test cases are written with the following signature:
#Test
public void test_Name() throws Exception {
//your test definition
}
You can also read the Official Documentation of Spring Boot https://spring.io/guides/gs/testing-web/

Cannot resolve this error: Failed to configure a DataSource

I am learning Spring Boot and in my first set up I got this problem:
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured
I looked up solutions on the web and did find some, including those from Stackoverflow, but none of them works.
My simple code:
#SpringBootApplication
#RestController
public class SpringBootDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootDemoApplication.class, args);
}
#RequestMapping(value = "/")
public String response(){
return "You made it!";
}
}
My POM:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</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>
</dependencies>
My application.properties:
spring.datasource.url=jdbc:mysql://localhost:3306/hrdb?autoReconnect=true
spring.datasource.username=root
spring.datasource.password=passw0rd
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
I also created a file as the following:
#Configuration
public class DBConfig {
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/hr?autoReconnect=true");
dataSource.setUsername("root");
dataSource.setPassword("passw0rd");
return dataSource;
}
}
I got the mentioned error either in Unit Test or starting the service. The only way I find out to make it work is to disable data source auto config:
#SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
Need your help. Thanks.
Check your DB config - it seems to overwrite Spring's default data source, but the url is different than in application.properties: "jdbc:mysql://localhost:3306/hr?autoReconnect=true"
In the properties you have:
"jdbc:mysql://localhost:3306/hrdb?autoReconnect=true"
"hr" vs "hrdb".
I would get rid of this class altogether and instead declare the relevant JDBC driver in your pom.xml and let Spring take care of the connection.

Using Weld with Dropwizard

I am trying to use Weld-SE for dependency injection in a dropwizard application. I can bootstrap Weld and inject in the Application class like so:
public class App extends Application<AppConfig> {
#Inject NameService service;
#Inject RestResource resource;
public static void main(String[] args) throws Exception {
Weld weld = new Weld();
WeldContainer container = weld.initialize();
App app = container.instance().select(App.class).get();
app.run(args);
weld.shutdown();
}
}
I have written a producer method in a separate class for the RestResource and this is also injected fine. However in the resource class the service is not injected:
#Path("/test")
#Produces(MediaType.APPLICATION_JSON)
public class RestResource {
#Inject NameService service;
#GET
public String test() {
return service.getName();
}
}
Here service is always null. Does anyone know how to make this work?
Dropwizard is using Jersey whose dependency injection is based on HK2 and not CDI. As a consequence you need to have a bridge between the two. This is what the jersey-gf-cdi is for:
<dependency>
<groupId>org.glassfish.jersey.containers.glassfish</groupId>
<artifactId>jersey-gf-cdi</artifactId>
</dependency>
You only need to have that JAR in the classpath. You can see here a configuration for Jetty here:
https://github.com/astefanutti/cdeye/blob/cd6d31203bdd17262aab12d992e2a730c4f8fdbd/webapp/pom.xml
And hereafter an example of CDI bean injection into JAX-RS resource:
https://github.com/astefanutti/cdeye/blob/cd6d31203bdd17262aab12d992e2a730c4f8fdbd/webapp/src/main/java/io/astefanutti/cdeye/web/BeansResource.java
For DropWizard 0.8.1 and Weld 2.2 the procedure is as follows:
1) Add dependencies to pom.xml:
<dependency>
<groupId>org.jboss.weld.servlet</groupId>
<artifactId>weld-servlet-core</artifactId>
<version>2.2.11.Final</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext.cdi</groupId>
<artifactId>jersey-cdi1x</artifactId>
<version>2.17</version>
</dependency>
<!-- the following additional dependencies are needed by weld -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
2) Add beans.xml file to src/main/resources/META-INF and add an inclusion filter for application packages. This is especially needed when using the shaded jar - without the filter Weld would scan every class in the shaded jar.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:weld="http://jboss.org/schema/weld/beans">
<weld:scan>
<weld:include name="com.example.**" />
</weld:scan>
</beans>
3) Register Weld's listener in your application class
#Override
public void run(Configuration conf, Environment env) throws Exception {
env.servlets().addServletListeners(new org.jboss.weld.environment.servlet.Listener());
}

Categories