Spring boot controller path giving 404 on websphere 9 - spring-boot

I have a spring boot 2.0 application that is working fine on embedded tomcat , now I generated a war from this applcation using apply plugin: 'war' in build.gradle file , the war is generated and deployed successfully on websphere 9 ... I tried hitting the context root, it gives the index.html correctly ... but when try to reach any path that was originally reached on the embedded tomcat it gives Error 404: java.io.FileNotFoundException: SRVE0190E: File not found: /path/mapped/in/controller ... can any one tell what is missing ?
this is the SpringBootApplication class code :
#SpringBootApplication
#MapperScan(basePackages = { "com.mypack.dao" })
public class MyApplication extends SpringBootServletInitializer{
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(MyApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}

Related

404 on Controller Endpoint Spring while running on customer server

I'm getting 404 consistently for a Gradle spring project while running on tomcat 8.5.
I created a simple project from https://start.spring.io and imported it into the spring tool suite.
When I run it as spring boot app, I'm able to hit the endpoint http://localhost:8080/healthCheck but when I add it to server I created (tomcat 8.5), I'm getting a 404 error on the same endpoint.
This is my simple controller:
#RestController
public class HealthCheckController {
#GetMapping("/healthCheck")
public String healthCheck() {
return "API is accessible";
}
}
This is my build.gradle:
plugins {
id 'org.springframework.boot' version '2.5.4'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}
group = 'com.demo'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'org.springframework.boot:spring-boot-starter-tomcat:2.5.4'
}
test {
useJUnitPlatform()
}
And this is my main class:
#SpringBootApplication
public class PracticeApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(PracticeApplication.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(PracticeApplication.class);
}
}
I have changed the server location to use Tomcat Installation and hence am able to hit http://localhost:8080 and it comes up with tomcat homepage.
Here's my directory structure for reference:
I'm new to gradle and spring so apologies if its a stupid thing that I'm doing wrong.
Please change your code as follows:
#SpringBootApplication
public class PracticeApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(PracticeApplication.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(PracticeApplication.class, HealthCheckController.class);
}
}
It seems that you need to list all the configuration classes and components in the application.
Still, I guess that overriding the configure() method is not necessary in your case, so I would also try:
#SpringBootApplication
public class PracticeApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(PracticeApplication.class, args);
}
}
So turns out Apache Tomcat does not take jar files and to run spring boot app on an external tomcat server (non-embedded ones), WAR file is needed to be created.
I added war to my build.gradle and gave it an alias as well
plugins {
id 'org.springframework.boot' version '2.5.4'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
id 'war'
}
war {
archiveName = 'practice.war'
}
After adding the above, I refreshed the Gradle project and restarted the server and then I hit the below endpoint:
http://localhost:8080/practice/healthCheck
This is different from how we hit the above endpoint on the embedded server which is:
http://localhost:8080/healthCheck
Another way to run this is to go to build/libs/ and copy the war into ROOT directory, then run startup.bat from apache/bin/

Can we implement Spring batch application without Spring Boot?

Can we implement Spring batch application without Spring Boot ?
Instead of an executable JAR you can also deploy a Spring Boot application as a WAR to JBoss.
The SpringBootApplication class will look a bit different:
#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);
}
}
And you have to use
<packaging>war</packaging>
Please find more information in the official documentation: https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-create-a-deployable-war-file

How prevent Spring boot war file load component twice in separated context?

I have a spring boot application, packaged as a war file and deployed on tomcat server. I noticed that some component load twice in startaup:
when application is started
when ServletInitializer is started.
It caused me some problem because one of my components is EnableAsync and should do some scheduled task frequently. when it load twice in tow separated context each task is done twice and make duplicated rows in database.
Is there a way that force some component just load in single context in Spring boot? it means prevent bean to be initialized in ServletInitializer for example.
That's my SpringBootServletInitializer code:
#SpringBootApplication
#EnableScheduling
#EnableAsync
public class TestApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
#Bean
public PasswordEncoder getPasswordEncoder(){
return new BCryptPasswordEncoder();
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(TestApplication.class);
}
}
Thanks to M. Deinum I found out there is an extra SpringBootServletInitializer in my code! I deleted it and Every thing is Ok now!

Spring Boot 2.0.2 + Flowable 6.3.1 Process Deployment

I am trying to integrate Spring Boot 2.0.2 with Flowable 6.3.1. and running into a problem where I am unable to deploy a process one-task-process.bpmn20.xml from the resources/processes/ folder. The XML file is not being picked up and the error says:
Caused by: org.flowable.engine.common.api.FlowableIllegalArgumentException: resource 'one-task-process.bpmn20.xml' not found
at org.flowable.engine.impl.repository.DeploymentBuilderImpl.addClasspathResource(DeploymentBuilderImpl.java:80) ~[flowable-engine-6.3.0.jar:6.3.0]
at com.stsi.pss.Application$1.run(Application.java:458) ~[classes/:na]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:797) [spring-boot-2.0.2.RELEASE.jar:2.0.2.RELEASE]
... 10 common frames omitted
My Spring Boot Application Starter file is as follows and it also prints out the class path which does not include the processes folder.
imports...
#Configuration
#ComponentScan
#EnableAutoConfiguration
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Bean
public CommandLineRunner init(final RepositoryService repositoryService,
final RuntimeService runtimeService,
final TaskService taskService) {
return new CommandLineRunner() {
#Override
public void run(String... strings) throws Exception {
ClassLoader cl = ClassLoader.getSystemClassLoader();
URL[] urls = ((URLClassLoader)cl).getURLs();
for(URL url: urls){
System.out.println(url.getFile());
}
System.out.println("Number of process definitions : "
+ repositoryService.createProcessDefinitionQuery().count());
System.out.println("Number of tasks : " + taskService.createTaskQuery().count());
runtimeService.startProcessInstanceByKey("oneTaskProcess");
System.out.println("Number of tasks after process start: "
+ taskService.createTaskQuery().count());
}
};
}
}
I would appreciate any help.
I made a mistake in naming the process definition file. I fixed the filename and the system is working as expected.

Why do I need main method if I develop web app as war using Spring Boot?

I am developing web app using Spring Boot. My typical deployment is generating war and place it in webapps folder in Tomcat directory.
I noticed with SpringBoot, I will need a main method. I am wondering why this is needed. If there is a way to avoid it, what would that be?
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
Main method is not required for the typical deployment scenario of building a war and placing it in webapps folder of Tomcat. All you need is:
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
}
However, if you want to be able to launch the app from within an IDE (e.g. with Eclipse's Run As -> Java Application) while developing or build an executable jar or a war that can run standalone with Spring Boot's embedded tomcat by just java -jar myapp.war command, an entry point class with a main method might be helpful.
To run in a separate web container
You don't need the main method, all you need is to do is to extend SpringBootServletInitializer as Kryger mentioned.
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
....
....
To run in the command line as a standalone application
Here you need the main method, so that you can run it using java -jar from the command line.
public class Application {
public static void main(String[] args){
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
}
....
....
Source: https://spring.io/guides/gs/convert-jar-to-war/
In Spring Boot one will basically need three things :
1) use the #SpringBootApplication annotation
2) extend SpringBootServletInitializer
3) overwrite the configure method as shown above
and that's it !

Resources