I am learning spring boot for work. Up to this point I have mostly worked with JavaScript and Node. I am working through a tutorial and came across this
package com.example.demosubmissionform;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
#ComponentScan
#SpringBootApplication
public class DemoSubmissionFormApplication extends SpringBootServletInitializer {
// #Override
// protected SpringApplicationBuilder configure(SpringApplicationBuilder
// application) {
// return application.sources(DemoSubmissionFormApplication.class);
// }
public static void main(String[] args) {
SpringApplication.run(DemoSubmissionFormApplication.class, args);
}
}
I have been playing around with the code trying to figure it how it works and learn the classes used. I have look through the docs but the information I found doesn't really explain what the SpringApplicationBuilder class is doing. I have commented it out and the program still works perfectly.
Sorry for being long winded. I appreciate any assistance.
P.S : The #ComponentScan annotation is redundant right? Seeing as its already comes with the #SpringBootApplication annotation.
The code using SpringApplicationBuilder is required when you are packaging your Spring Boot application as a war file and deploying it to an application server or Servlet container. If you're packaging your application is a jar file and running it using java -jar – the typical approach when using Spring Boot – you don't need the configure method and you don't need to extend SpringBootServletInitializer either.
You can learn a bit more about SpringBootServletInitializer, SpringApplicationBuilder and traditional war deployments in the reference documentation.
You are correct that the #ComponentScan annotation is redundant. As you said, it's already part of #SpringBootApplication.
Related
I am a beginner to Spring boot. When I created a spring boot application from https://start.spring.io/ and when I am going to run the application It shows the below White Label error page. It has only the newly created Application.java file. It's great pleasure to expect an answer from you!
Application.java
package com.markdown.auth.application;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
You have to add controllers and endpoints,which will return to you information that you want. Without these you'll get 404 error
You can add End Points means Controler and BL in which what you want.
https://spring.io/guides/gs/rest-service/
go through this link
i want to use the java websocket API in a Spring Boot application.
I created the following class as described here:
https://www.baeldung.com/java-websockets
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
#ServerEndpoint(value = "/test")
public class FrontendEndpoint {
#OnOpen
public void onOpen(Session session) throws IOException {
session.getBasicRemote().sendText("Test");
}
#OnMessage
public void onMessage(Session session, String message) throws IOException {
}
#OnClose
public void onClose(Session session) throws IOException {
}
#OnError
public void onError(Session session, Throwable throwable) {
}
}
I try to connect to that websocket but nothing happens. I saw a lot of articles in the internet but nothing helped me. I dont know how to get it to work.
When i try to connect to the websocket nothing happend.
Spring Boot version: 2.0.3
Websocket-API version: 1.1
I also don't see an open port for the websocket.
Thanks
BR
I once created a sample application with Spring Boot and Websocket API
https://github.com/simasch/spring-boot-websocket
but the problem is that the ServerEndpoint is not managed by Spring but by the Websocket implementation. So this is maybe not the way you should use websockets with Spring Boot.
I would recommend to have a look how Spring think that Websockets should be used:
https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#websocket
It's a bit late, but in case someone will come here for a solution.
It is not covered in Spring documentation how to use Java WebSocket API (JSR-356) in Spring and I didn't manage to find any tutorial describing how to achieve it despite I've spent several hours googling it.
In order to use Java WebSocket API with Spring you should use class org.springframework.web.socket.server.standard.SpringConfigurator:
https://docs.spring.io/spring/docs/current/javadoc-api/index.html?org/springframework/web/socket/server/standard/SpringConfigurator.html
from
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>...</version>
</dependency>
Just add it to your
#ServerEndpoint(... configurator = SpringConfigurator.class)
and it is done. Your annotated class becomes a usual Spring-managed component legal for #Autowired injection and so on.
Hope it helps someone :)
UPD.
It should be mentioned, that JSR 356 WebSocket initialization through the SpringConfigurator is only supported in .war projects, that are to be deployed as usual artifacts in servlet container.
It will not work as expected when project is packaged in executable Spring Boot .jar or Spring Boot executable .war and when it is deployed it standalone mode via java -jar {app}
I didn't manage to find a way to initialize JSR 356 WebSocket with #Autowired Spring components in it in Spring Boot environment in executable archive.
It is possible to deploy JSR 356 WebSocket via ServerEndpointExporter.setAnnotatedEndpointClasses(...), but every class provided must have a no-arg constructor otherwise exception will be thrown. #Autowired field will not be processed by Spring in this case.
If you want to use java websocket API in a Spring Boot application you have to add this to spring configuration
#Configuration
public class WebSocketConfig {
#Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
Here is a full article.
Why should we extend SpringBootServletInitializer in order to run a SpringBoot application to a external tomcat?
If without extending SpringBootServletInitializer it runs on embedded tomcat then why it is necessary to extendSpringBootServletInitializer while deploying it to an external tomcat?
Older Servlet containers don’t have support for the ServletContextInitializer bootstrap process used in Servlet 3.0. You can still use Spring and Spring Boot in these containers but you are going to need to add a web.xml to your application and configure it to load an ApplicationContext via a DispatcherServlet.
Inorder to create deployable war file is to provide a SpringBootServletInitializer subclass and override its configure method. This makes use of Spring Framework’s Servlet 3.0 support and allows you to configure your application when it’s launched by the servlet container. Typically, you update your application’s main class to extend SpringBootServletInitializer.
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
You can refer below link
https://docs.spring.io/spring-boot/docs/current/reference/html/howto-traditional-deployment.html
Here is some more information :
In order to deploy a Servlet based web application(like Spring) you actually need to provide traditional web.xml .
We can also do the same thing programatically using WebApplicationInitializer interface. As per the docs
Interface to be implemented in Servlet 3.0+ environments in order to
configure the ServletContext programmatically -- as opposed to (or
possibly in conjunction with) the traditional web.xml-based approach.
As SpringBoot suggests to use JavaConfiguration over xml configuration.
It uses JavaConfiguration instead of web.xml.
It has SpringBootServletInitializer class which eventually implement the WebApplicationInitializer interface and override its onStartup to configure things.
What could be the problem if Spring Boot cannot resolve view with specific name?
I have developed many Spring Boot applications before and have never encountered this problem.
I have following folder structure:
/src/main/java
/src/main/resources/config
/src/main/resources/static
/src/main/resources/static/partials
/src/main/resources/static/resources
Image:
/src/main/resources/static/resources folder is not making problems for having resources name. I tried renaming it and it didn't solve problem.
I am using Maven and I have parent project which has multiple children projects.
Module for the rest api contains many configuration classes, including configurations for security.
Everything is working as it should, application can be started without errors, but when I tried to add static content I encountered this problem.
From the following example (example) we can see that Spring Boot should automatically maps src/main/resources/static/index.html to the root path, but that is not happening in my application. From the log I can see that Spring didn't find mapping for /.
I am able to run that example normally, but in my application it is not working.
Because Spring didn't map automatically I created WelcomeController which should return view:
#Controller
public class WelcomeRestController {
#RequestMapping("/")
public String welcome() {
return "index.html";
}
}
After I did that, mapping is found, but Spring reports that it couldn't resolve view with name index.html even if it exists.
I tried adding static content to src/main/webapp/static folder even if it is not recommended and it also didn't work, same problem, cannot resolve view.
I also tried to configure using
#Configuration
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
#Override public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index.html");
}
}
Again, view cannot be resolved.
My application's start point:
#Import(MyRestServiceConfiguration.class)
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
public static void main(final String[] args) {
SpringApplication.run(Application.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(Application.class);
}
}
I am using embedded Tomcat.
Is it possible that security configurations or some other configurations except WebMvcConfigurerAdapter are having influence on views?
I am trying to resolve this issue for hours but I can't find soulution. Any help would be appreciated.
EDIT:
I am not building application using Maven, just running Application.java as Java Application, so Maven should not be a problem.
EDIT:
Content of index.html:
<!DOCTYPE html>
<html >
<head lang="en">
</head>
<body>
<div>Hello</div>
</body>
</html>
I have found a solution, but I am not really sure why this makes problem. Please post your answer if you know why is this happening.
The problem was #EnableWebMvc annotation in MyRestServiceConfiguration
#Configuration
// #EnableWebMvc
#Import(MyServiceConfiguration.class)
public class MyRestServiceConfiguration {
}
After removing it, everything works as it should.
From Spring Boot guide:
Normally you would add #EnableWebMvc for a Spring MVC app, but Spring Boot adds it automatically when it sees spring-webmvc on the classpath. This flags the application as a web application and activates key behaviors such as setting up a DispatcherServlet.
It's clear that #EnableWebMvc annotation is not needed, but why does it make problems?
EDIT:
From Spring Boot reference:
The easiest way to take complete control over MVC configuration is to provide your own #Configuration with the #EnableWebMvc annotation. This will leave all MVC configuration in your hands.
From Spring's #EnableWebMvc documentation:
Adding this annotation to an #Configuration class imports the Spring MVC configuration from WebMvcConfigurationSupport, e.g.:
#Configuration
#EnableWebMvc
#ComponentScan(basePackageClasses = { MyConfiguration.class })
public class MyWebConfiguration {
}
So, the problem was that #EnableWebMvc annotation dissabled default Spring Boot's configuration and because of that Spring didn't know where to look for static resources. If I got something wrong, please correct me.
As in spring site isn't allowed to ask question i will write here my question to Spring authors.
I would like to know how supposed to use spring documentation.
I spent a lot of time in Spring boot reference guide. Only for understand how spring boot is working.
There are some examples work principle of which are not explained in documentation. Or explained like this
11.3.2 The #EnableAutoConfiguration annotation
The second class-level annotation is #EnableAutoConfiguration. This annotation tells Spring Boot to “guess” how you will want to configure Spring, based on the jar dependencies that you have added. Since spring-boot-starter-web added Tomcat and Spring MVC, the auto-configuration will assume that you are developing a web application and setup Spring accordingly.
And there are nothing about how it works. Some kind of philosophy.
I read a lot of tutorial from other developer and they give the exactly same information as original documentation. Like nobody knows how it really works and what will happen if you will not use tutorial example)).
Now I have to handle another programmers code on spring boot and I can't find answer to one question. What method will call after this application.main?
import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.endpoint.EnvironmentEndpoint;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
import javax.inject.Inject;
/**
* Root entry of our service, starting the Spring container and configuring our system.
*/
#SpringBootApplication
#EnableScheduling
public class Application {
#Inject
private EnvironmentEndpoint environmentEndpoint;
protected Application() {
}
/**
* Main method, used to run the application.
*/
public static void main(final String[] args) {
final SpringApplication application = new SpringApplication(Application.class);
application.run(args);
}
}