Getting a 404 when trying to load index.jsp using Spring MVC - java

Even after checking other answers and comparing the code with other applications that I have developed, I can't get to load index.jsp properly. I'm working with Spring MVC, using annotations. The thing is that I have done the same before and it has worked, what could my error be this time?
MvcConfig:
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = { "tool.controller" })
public class MvcConfig extends WebMvcConfigurerAdapter {
private static final String VIEW_CONTROLLER = "/index.htm";
private static final String VIEW_NAME = "/view/index.jsp";
#Override
public void addViewControllers(final ViewControllerRegistry registry) {
registry.addViewController(VIEW_CONTROLLER).setViewName(VIEW_NAME);
}
#Override
public void configureDefaultServletHandling(final DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
WebInitializer:
public class WebInitializer implements WebApplicationInitializer {
#Override
public void onStartup(final ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(BasicConfig.class, MvcConfig.class);
servletContext.addListener(new ContextLoaderListener(context));
AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
ServletRegistration.Dynamic dispatcher;
dispatcher = servletContext.addServlet("dispatcher",
new DispatcherServlet(dispatcherContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
IndexController:
#Controller
public class IndexController {
private static final String INDEX_VIEW = "/view/index.jsp";
#RequestMapping(value = { "/", "/index" })
public ModelAndView home() {
ModelAndView modelAndView = new ModelAndView(INDEX_VIEW);
return modelAndView;
}
}
Folder Structure:
Folder Structure
Console messages from Tomcat initiallization that could be relevant:
Console messages
Any help will be appreciated, thanks!
EDIT: build.gradle
apply plugin: 'base'
apply plugin:'war'
apply plugin: 'jetty'
apply plugin: 'java'
apply plugin: 'eclipse-wtp'
apply plugin:'idea'
ext.springVersion='4.1.4.RELEASE'
ext.hibernateVersion='4.3.8.Final'
ext.hibernateValidatorVersion='5.1.3.Final'
repositories {
mavenCentral()
}
dependencies {
compile 'org.slf4j:slf4j-api:1.7.10'
compile 'org.slf4j:slf4j-simple:1.7.10'
compile 'ch.qos.logback:logback-core:1.1.2'
providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
compile 'org.springframework.data:spring-data-jpa:1.3.0.RELEASE'
compile "org.springframework:spring-jdbc:$springVersion"
compile "org.springframework:spring-tx:$springVersion"
compile "org.springframework:spring-orm:$springVersion"
compile "org.springframework:spring-aop:$springVersion"
compile "org.springframework:spring-webmvc:$springVersion"
compile "org.springframework:spring-oxm:$springVersion"
compile "org.springframework.security:spring-security-core:4.1.3.RELEASE"
compile "org.hibernate:hibernate-entitymanager:$hibernateVersion"
compile "org.hibernate:hibernate-core:$hibernateVersion"
compile "org.hibernate:hibernate-validator:$hibernateValidatorVersion"
compile "org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.0.Final"
compile 'org.postgresql:postgresql:9.4-1201-jdbc41'
compile 'javax.servlet.jsp:javax.servlet.jsp-api:2.3.1'
compile 'javax.servlet:jstl:1.2'
testCompile "org.mockito:mockito-core:1.+"
testCompile 'junit:junit:4.11'
}
eclipse {
project.natures "org.springframework.ide.eclipse.core.springnature"
}

Also try to modify your controller class according to spring's good practices.
#Controller
public class IndexController {
//private static final String INDEX_VIEW = "/view/index.jsp";
#RequestMapping(value = { "/", "/index" })
public ModelAndView home() {
ModelAndView modelAndView = new ModelAndView("index");
return modelAndView;
}
}

I have apparently found what was the problem. First of all, I'm working on Eclipse IDE. The solution that I came to was adding the folder "webapp" to the "Web Deployment Assembly" in the project's properties. After doing this, the index.jsp is loading properly and I'm not getting a 404 error anymore.

Related

Can't open OpenApi (Swagger) page

Gradle:
implementation group: 'org.springdoc', name: 'springdoc-openapi-ui', version: '1.6.13'
implementation group: 'io.swagger.core.v3', name: 'swagger-annotations', version: '2.2.7'
Properties:
springdoc.swagger-ui.enabled=true
springdoc.swagger-ui.path=/swagger-ui.html
Controller:
#RestController
#RequestMapping("/api/v1/cheque")
#FieldDefaults(level = AccessLevel.PRIVATE,makeFinal = true)
public class ChequeController {
ProductService productService;
public ChequeController(ProductService productService) {
this.productService = productService;
}
#GetMapping(value = "/get/{id}", produces = "application/json")
public Optional<Product> getByid(#PathVariable Long id) {
return productService.getById(id);
}
#GetMapping("/test")
public String test() {
return "test";
}
}
Conf:
#Configuration
public class OpenApiConfiguration {
#Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()
.info(
new Info()
.title("Example Swagger Api")
.version("1.0.0")
);
}
}
Trying to open in localhost:8080/swagger-ui.html and getting:
Whitelabel Error Page There was an unexpected error (type=Not Found, status=404). in https://springdoc.org/#getting-started saying, that it will automatically deploy swagger-ui to a spring-boot application
what im doing wrong
For swagger v3+, the swagger ui default access is now swagger-ui/ instead of swagger-ui.html
You should be able to access by amending your url to localhost:8080/swagger-ui/

Why web service and proxy client not connecting?

I have an application where I try to combine Spring MVC and Apache CFX(soap) web services. When I run just the app, everything seems fine, I see generated WSDL by this link(http://localhost:8080/services/customer?wsdl). But when I run tests, it throws WebServiceException: Could not send Message... Connection refused.
I've opened all ports for public, private and domain area through Windows Firewall Defender. Maybe I've missed something.
In a desperate attempt to investigate it, I've checked the link with this command (wsimport -keep -verbose http://localhost:8080/services/customer?wsdl). As a result, it gave this:
[ERROR] Server returned HTTP response code: 403 for URL: http://localhost:8080/services/customer?wsdl
Failed to read the WSDL document: http://localhost:8080/services/customer?wsdl, because 1) could not find the document; /2) the document could not be read; 3) the root element of the document is not <wsdl:definitions>.
[ERROR] Could not find wsdl:service in the provided WSDL(s):
At least one WSDL with at least one service definition needs to be provided.
Now I do not know which way to dig.
WebServiceDispatcherServletInitializer
public class WebServiceDispatcherServletInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(WebServiceConfig.class);
servletContext.addListener(new ContextLoaderListener(context));
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new CXFServlet());
dispatcher.addMapping("/services/*");
}
}
WebServiceConfig
#Configuration
public class WebServiceConfig {
#Bean(name = Bus.DEFAULT_BUS_ID)
public SpringBus springBus() {
return new SpringBus();
}
#Bean
public Endpoint endpoint() {
EndpointImpl endpoint = new EndpointImpl(springBus(), new CustomerWebServiceImpl() );
endpoint.publish("http://localhost:8080/services/customer");
return endpoint;
}
}
ClientConfig
#Configuration
public class ClientConfig {
#Bean(name = "client")
public Object generateProxy() {
return proxyFactoryBean().create();
}
#Bean
public JaxWsProxyFactoryBean proxyFactoryBean() {
JaxWsProxyFactoryBean proxyFactory = new JaxWsProxyFactoryBean();
proxyFactory.setServiceClass(CustomerWebService.class);
proxyFactory.setAddress("http://localhost:8080/services/customer");
return proxyFactory;
}
}
CustomerWebServiceImplTest
#ActiveProfiles(profiles = "test")
#ContextConfiguration(classes = {
PersistenceConfig.class,
RootConfig.class,
WebServiceConfig.class,
ClientConfig.class
})
#WebAppConfiguration
public class CustomerWebServiceImplTest {
private ApplicationContext context = new AnnotationConfigApplicationContext(ClientConfig.class);
private CustomerWebService customerWsProxy = (CustomerWebService) context.getBean("client");
#Test
public void addCustomer() {
CustomerDto customer = new CustomerDto();
customer.setName("John");
assertEquals("Hello " + customer.getName(), customerWsProxy.addCustomer(customer));
}
}
Could you give a hint where the error might be?
UPD: I checked this setup on PC where I and my applications have full access rights and it still throws the Exception.
A solution was quite simple - just need to add #RunWith(SpringRunner.class). Because this annotation is run spring beans, not #WebAppConfiguration with #ContextConfiguration.
This is how it will look like
#RunWith(SpringRunner.class)
#ContextConfiguration(classes = {
RootConfig.class,
WebServiceConfig.class,
ClientConfig.class
})
public class CustomerWebServiceImplTest {
...
}

AOP not invoked by annotation

I am trying to invoke a AOP method for every method that is annotated with #Timed.
My AOP MyTracer.java
#Aspect
public class MyTracer {
private static final Tracer tracer = Tracing.getTracer();
private static final Logger log = Logger.getLogger(MyTracer.class.getName());
#Around("#annotation(timed)")
public Object trackExecutionTime(ProceedingJoinPoint proceedingJoinPoint, Timed timed) throws Throwable {
String methodName = proceedingJoinPoint.getSignature().getName();
log.info("Using AOP for method name" + methodName);
log.info("Using AOP for param name" + timed.label());
return output;
}
}
}
My Annotation
Timed.java
#Target({ElementType.METHOD})
#Retention(RetentionPolicy.RUNTIME)
public #interface Timed {
String label() default "label";
}
Finally my business code
HelloWorld.java
#Override
#Timed(label = "myMetrics")
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
log.info("Servlet called");
PrintWriter out = resp.getWriter();
out.println("Hello, world - Flex Servlet");
}
At runtime, I am getting logs from the servlets but not the MyTracer class.
Ok, I figured it out. The build.gradle was missing the following. I replaced
compile group: 'org.aspectj', name: 'aspectjtools', version: '1.6.2'
with
buildscript {
repositories {
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
classpath "gradle.plugin.aspectj:gradle-aspectj:0.1.6"
}
}
project.ext {
aspectjVersion = "1.8.2"
}
apply plugin: "aspectj.gradle"

How to use SpringSecurity and JDBI

I'm trying to configure a server with Spring. I want to use Spring security and JDBI at the same time.
So I've configured the datasource of my server (?) and linked it to JDBI. But I'm not able to use this datasource in the WebSecurityConfig.
This is my Main config java file :
#SpringBootApplication
#EnableAutoConfiguration
public class Application extends WebMvcConfigurerAdapter {
private static DBI dbi = null;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
static DBI getDbi() {
if(dbi == null) {
DataSource ds = JdbcConnectionPool.create("jdbc:h2:mem:test", "ndl", "ndl");
dbi = new DBI(ds);
}
return dbi;
}
}
This is the file for security spring
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private DataSource dataSource;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login.html")
.permitAll()
.and()
.logout()
.permitAll();
http.csrf().disable();
}
#Autowired
public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery(
"select username,password from users where username=?")
.authoritiesByUsernameQuery(
"select username, role from users where username=?");
}
}
I got this error.
Field dataSource in rest.WebSecurityConfig required a bean of type 'javax.sql.DataSource' that could not be found.
I tried to write the DataSource ds in the class (and not in the method). And add to it the annotation #Bean. But i got an other error
public static DataSource ds = JdbcConnectionPool.create("jdbc:h2:mem:test", "ndl", "ndl");
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Bean
public static DataSource getDataSource(){
return ds;
}
And the error
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'webSecurityConfig': Injection of autowired dependencies failed; nested exception is java.lang.NoClassDefFoundError: org/springframework/jdbc/core/support/JdbcDaoSupport
I hope you have any ideas...
Thanks ;)
Problem found.
I missed the following dependency : spring-jdbc
So my final build.gradle is
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.8.RELEASE")
}
}
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
jar {
baseName = 'gs-rest-service'
version = '0.1.0'
}
repositories {
mavenCentral()
maven {
url 'https://repo.spring.io/libs-milestone'
}
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
testCompile('org.springframework.boot:spring-boot-starter-test')
compile("org.springframework.boot:spring-boot-starter-security")
testCompile("org.springframework.security:spring-security-test")
compile group: 'org.jdbi', name: 'jdbi', version: '2.4.2'
compile group: 'com.h2database', name: 'h2', version: '1.3.148'
compile group: 'org.springframework', name: 'spring-jdbc', version: '4.3.8.RELEASE'
}

Problems with controller mapping in Spring MVC

There are similar topics, but they all use xml configuration files. The reason why I'm writing this question is that I'm using annotations.
I experience problems running my app:
getting “WARN org.springframework.web.servlet.PageNotFound - No
mapping found for HTTP request with URI …” when trying to setup
Spring servlet
getting error 404 when trying to run it on server
Here is my code (package and imports are skipped):
1) initializer
public class WebInitializer implements WebApplicationInitializer{
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext ctx =
new AnnotationConfigWebApplicationContext();
ctx.register(AppConfig.class);
ctx.setServletContext(servletContext);
ServletRegistration.Dynamic servlet =
servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
servlet.addMapping("/");
servlet.setLoadOnStartup(1);
}
}
2) app config
#Configuration
#ComponentScan("ua.kiev.prog")
#EnableWebMvc
public class AppConfig {
#Bean
public EntityManager entityManager() {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("AdvJPA");
return emf.createEntityManager();
}
#Bean
public AdvDAO advDAO() {
return new AdvDAOImpl();
}
#Bean
public UrlBasedViewResolver setupViewResolver() {
UrlBasedViewResolver resolver = new UrlBasedViewResolver();
resolver.setPrefix("/WEB-INF/pages/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
resolver.setOrder(1);
return resolver;
}
#Bean
public CommonsMultipartResolver multipartResolver() {
return new CommonsMultipartResolver();
}
}
3) controller
#Controller
#RequestMapping("/Advertisement")
public class MainController {
#Autowired
private AdvDAO advDAO;
#RequestMapping("/")
public ModelAndView listAdvs() {
return new ModelAndView("index", "advs", advDAO.list());
}
#RequestMapping(value = "/add_page", method = RequestMethod.POST)
public String addPage(Model model) {
return "add_page";
}
#RequestMapping(value = "/search", method = RequestMethod.POST)
public ModelAndView search(#RequestParam(value="pattern") String pattern) {
return new ModelAndView("index", "advs", advDAO.list(pattern));
}
// more code goes here
}
The controller is mapped to /Advertisement, so app should be available at URL localhost:8080/Advertisement/ but it isn't. When I change mapping in annotation to "/" - it becomes available at localhost:8080/Advertisement/. How can it be?
And when I change it back to "/Advertisement" - the same probleb accurs (error 404 and exception "No mapping found for HTTP request with URI …")
So, where I've made a mistake in my code?
Or maybe the problem is in Eclipse/TomCat/Maven?
Source - https://github.com/KostyantynPanchenko/prog.kiev.ua.lesson09.adv
You should change mapping
#Controller
#RequestMapping("/")
public class MainController {
#Autowired
private AdvDAO advDAO;
#RequestMapping("/Advertisement")
public ModelAndView listAdvs() {
return new ModelAndView("index", "advs", advDAO.list());
}
The mistake that a mapper used the value from the annotation to match the request URL, and it can't match the last slash. Note, it should not happen in the above code.
How are you running the application? Atleast in tomcat each deployed application is served from specific context path. Context path is determined from the base file name, more on that here.
So if you're deploying Advertisement.war all requests to the app will be served from localhost:8080/Advertisement/ even though you're declaring the DispatcherServlet and Controller to /

Categories