Unable to call spring boot application service when deployed to tomcat server. - spring

I have a SpringBootApp that I can run in eclipse by right-clinging and then selecting Run as -> Java Application. However, when I build a .war file and deploy it to my tomcat server. The console looks as though the application should have deployed but I'm unable to hit my rest services. I'm getting a 404 error. I really have no clue why it is not working so if anyone knows a solution could you explain why... Also, when I look in my war file i see all the classes files needed to deploy the application.
You can download the code github.
Controller:
package com.sample.pkg;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
#Controller
#ComponentScan("com.sample.pkg")
public class SampleController {
#Autowired
SampleComponent component;
#RequestMapping("/sendOption")
public String update(#RequestParam(value = "option") String option) {
if (option.equalsIgnoreCase("option1")) {
component.updateStatus(true);
return "Something was updated";
} else if (option.equalsIgnoreCase("option2")) {
component.updateStatus(false);
return "Something else was updated";
}
return "You have entered in an option that is invalid. Please enter a valid option.";
}
#RequestMapping("/getOption")
public String control() {
if (component.getStatus()) {
return "option1";
} else if (!component.getStatus()) {
return "option2";
}
return "error";
}
}
Application.java
package com.chicken.door;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.context.annotation.PropertySource;
#SpringBootApplication
#PropertySource("classpath:application.properties")
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);
}
}
build.gradle
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.3.RELEASE")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'war'
war {
baseName = 'gs-spring-boot'
version = '0.1.0'
}
jar {
baseName = 'gs-spring-boot'
version = '0.1.0'
}
repositories {
mavenCentral()
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
compile("org.springframework.boot:spring-boot-starter-actuator")
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
testCompile("org.springframework.boot:spring-boot-starter-test")
}
Output:
2017-07-18 21:32:13.246 INFO 947 --- [ main] com.sample.pkg.Application : Started Application in 10.6 seconds (JVM running for 10.976)

Related

Default profile values are not returned when specific profile selected in Spring Cloud Config

I'm moving from a local application.yml configuration file to a config server managed configuration.
My application.yml file contains 2 (or more) profiles in the same file, in the format:
spring.application.name: config-client
app.myvar1: "Var 1 in default profile"
app.myvar2: "Var 2 in default profile"
---
spring.config.activate.on-profile: docker
app.myvar1: "Var 1 in docker profile"
When I test this configuration file in a NOT config-server environment, I the result reading from the specific profile, and if not found, reading from default. Sample
Correct result when I test without config-server
Profile: docker
MyVar1=Var 1 in docker profile
MyVar2=Var 2 in default profile
For testing I'm using a simple program:
package com.bthinking.configclient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#SpringBootApplication
#RestController
public class ConfigClientApplication {
#Autowired
private Environment environment;
#Value("${app.myvar1:MyVar1 not found}")
String myVar1;
#Value("${app.myvar2:MyVar2 not found}")
String myVar2;
public static void main(String[] args) {
SpringApplication.run(ConfigClientApplication.class, args);
}
#RequestMapping("/")
public String index() {
StringBuffer b = new StringBuffer();
for (String profile : environment.getActiveProfiles()) {
b.append(String.format("Profile: %s</br>", profile));
}
b.append(String.format("MyVar1=%s</br>", myVar1));
b.append(String.format("MyVar2=%s</br>", myVar2));
return b.toString();
}
}
And I start the program with (I use gradle):
gradle :config-client:bootRun --args='--spring.profiles.active=docker'
But, when I migrate to config server, moving the file to a config-repo (I'm using file based repor), I get the invalid result (it's unable to read the variable in the default section). I have also tried with --spring.profiles.active=docker,default with no change
Profile: docker
MyVar1=Var 1 in docker profile
MyVar2=MyVar2 not found
For reference, my config-server has the following configuration:
server.port: 8888
spring.application.name: config-server
spring.cloud.config.server.native.searchLocations: file:${PWD}/config-repo
# spring.cloud.config.server.native.searchLocations: file:/Users/jmalbarran/Projects/BTH/BTH/SPB_SpringBoot/bugs/config/config-repo
logging.level:
root: debug
---
spring.config.activate.on-profile: docker
spring.cloud.config.server.native.searchLocations: file:/config-repo
The main class
package com.bthinking.configserver;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
#EnableConfigServer
#SpringBootApplication
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
And the build.gradle
plugins {
id 'org.springframework.boot' version '2.4.1'
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
id 'java'
}
group = 'com.b-thinking'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
maven { url 'https://repo.spring.io/milestone' }
}
ext {
set('springCloudVersion', "2020.0.0")
}
dependencies {
implementation 'org.springframework.cloud:spring-cloud-config-server'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
test {
useJUnitPlatform()
}
And I start it with:
gradle :config-server:bootRun --args='--spring.profiles.active=native'
NOTE: As I think this a bug, I have also created an issue in github. Check in Issue
After the #spencergibb (Thanks!) comment, I tried with the version 3.0.1, and it solves the problem.
This is now my build.gradle
plugins {
id 'org.springframework.boot' version '2.4.1'
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
id 'java'
}
group = 'com.b-thinking'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
maven { url 'https://repo.spring.io/milestone' }
}
ext {
set('springCloudVersion', "2020.0.0")
}
dependencies {
implementation 'org.springframework.cloud:spring-cloud-config-server:3.0.1'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
test {
useJUnitPlatform()
}
It's amazing, because the version 3.0.1 is reported solving the opposite bug (the default configuration override the specific), but I imagine that the review solved both.
For references, this were the related issues
Issue#1777 Profile not correct with SpringBoot 2.4.1 + Ilford 2020.0.0 (working with 2.4.1 + Ilford 2020.0.0-RC1)
Issue#1778 multidocument files from config server have the same property name

Why cant i import #RestController spring boot

enter image description herei'm just trying to set up a simple spring boot application that has rest controller. But cant import Rest Controller. Here is my main method
package com.test.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RestController;
#RestController
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
And here is my build.gradle. the script collects all the jars on the classpath and builds a single jar.
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:2.2.1.RELEASE")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
bootJar {
baseName = 'gs-spring-boot-docker'
version = '0.1.0'
}
repositories {
mavenCentral()
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-rest'
implementation 'org.springframework.boot:spring-boot-starter-web'
compile("org.springframework.boot:spring-boot-starter-web")
testCompile("org.springframework.boot:spring-boot-starter-test")
}
Any Ideas? Thanks
You are missing import for #RequestMapping("/").
import org.springframework.web.bind.annotation.RequestMapping;
I invalidated and restarted the caches which worked!

I am trying to load a jsp using spring boot with gradle but I am only getting internal server error

I am new to spring boot and trying to load a jsp page but even after trying a lot and searching on internet I couldn't find any solution of it. I am unable to get the error causing part in this complete process.
To build this all I used command 'gradle build' on command prompt.
To start the server I used command :- java -jar build\libs\one-0.0.1-SNAPSHOT.war
then I on browser I typed :- http://localhost:8080/helloWorld
Here is my build.gradle
plugins {
id 'org.springframework.boot' version '2.2.2.RELEASE'
id 'io.spring.dependency-management' version '1.0.8.RELEASE'
id 'java'
id 'war'
}
group = 'com.tm'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
configurations {
developmentOnly
runtimeClasspath {
extendsFrom developmentOnly
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-web'
providedRuntime 'javax.servlet:jstl'
providedRuntime 'org.apache.tomcat.embed:tomcat-embed-jasper'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
test {
useJUnitPlatform()
}
This is my java code of controller HelloJSPController.java, it is in this folder structure: \src\main\java\com\tm\one
package com.tm.one;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
#Controller
public class HelloJSPController
{
#GetMapping("/helloWorld")
public String helloWorld()
{
return "helloWorld";
}
}
This is WebMvcConfig.java configuration file
package com.tm.one.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
#Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter
{
#Bean
public InternalResourceViewResolver viewResolver()
{
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/jsp/");
resolver.setSuffix(".jsp");
return resolver;
}
}
OR I tried this two lines in application.propertes also instead of above configuration file
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
This is JSP file helloWorld.jsp in folder structure :-- \one\src\main\webapp\WEB-INF\jsp
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello</title>
</head>
<body>
<h2>Hello everyone I am AD</h2>
</body>
</html>
This is error I am getting on browser
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Mon Jan 13 16:53:14 IST 2020
There was an unexpected error (type=Internal Server Error, status=500).
Error resolving template [helloWorld], template might not exist or might not be accessible by any of the configured Template Resolvers
This is OneApplication.java
package com.tm.one;
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;
#SpringBootApplication
public class OneApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(OneApplication.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(OneApplication.class);
}
}
Had the same issue as you, and I believe it's not due to the java code. The only solution I found was switching to maven. Absolutely no other change in the java code, only build.gradle -> pom.xml.

Dependencies for Spring Integration Amqp in Spring Boot

In order to use Spring Integration Amqp in a Spring Boot application, what are the dependencies I need to include?
Spring Boot version is 2.0.5.
Current dependencies I have are spring-boot-starter-integration and spring-integration-amqp
Error messages are classes like SimpleMessageListenerContainer and AmqpInboundChannelAdapter are not found on the classpath.
UPDATE:
My build.gradle entries --
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:2.0.5.RELEASE")
}
}
dependencies {
compile('org.springframework.boot:spring-boot-starter-integration')
compile('org.springframework.boot:spring-boot-starter-amqp')
compile('org.springframework.integration:spring-integration-amqp')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
I had to add the following dependencies to resolve the classes in question (the last in the list did it, using latest spring initalizr, spring-boot 2.0.5)
dependencies {
implementation('org.springframework.boot:spring-boot-starter-amqp')
implementation('org.springframework.boot:spring-boot-starter-integration')
testImplementation('org.springframework.boot:spring-boot-starter-test')
compile 'org.springframework.integration:spring-integration-amqp'
}
To be fair, this answer was already given, just not for gradle.
I am using gradle 4.10.2 on a linux machine, spring-boot initialzr with the options RabbitMQ and Spring-Integration. Here are the changed files:
build.gradle
buildscript {
ext {
springBootVersion = '2.0.5.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
implementation('org.springframework.boot:spring-boot-starter-amqp')
implementation('org.springframework.boot:spring-boot-starter-integration')
testImplementation('org.springframework.boot:spring-boot-starter-test')
compile 'org.springframework.integration:spring-integration-amqp'
}
Implementation of Example 12.2.1 Configuring with Java Configuration from the Spring Integration docs:
package com.example.integrationamqp;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.integration.amqp.inbound.AmqpInboundChannelAdapter;
import org.springframework.integration.amqp.inbound.AmqpInboundGateway;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.MessagingException;
#SpringBootApplication
public class IntegrationAmqpApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(IntegrationAmqpApplication.class)
.web(WebApplicationType.NONE)
.run(args);
}
#Bean
public MessageChannel amqpInputChannel() {
return new DirectChannel();
}
#Bean
public AmqpInboundChannelAdapter inbound(SimpleMessageListenerContainer listenerContainer,
#Qualifier("amqpInputChannel") MessageChannel channel) {
AmqpInboundChannelAdapter adapter = new AmqpInboundChannelAdapter(listenerContainer);
adapter.setOutputChannel(channel);
return adapter;
}
#Bean
public SimpleMessageListenerContainer container(ConnectionFactory connectionFactory) {
SimpleMessageListenerContainer container =
new SimpleMessageListenerContainer(connectionFactory);
container.setQueueNames("foo");
container.setConcurrentConsumers(2);
// ...
return container;
}
#Bean
#ServiceActivator(inputChannel = "amqpInputChannel")
public MessageHandler handler() {
return new MessageHandler() {
#Override
public void handleMessage(Message<?> message) throws MessagingException {
System.out.println(message.getPayload());
}
};
}
}
Add this dependency:
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
And are you sure you have this one?:
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-amqp</artifactId>

Gradle build with fatJar plugin and SpringBoot application gives 'Application startup failed'

Everything was working fine when starting my app using Intellij. But when I made fatJar (with gradle plugin: eu.appsatori.fatjar) and execute:
java -jar myapp.jar
I'm getting something like this:
11:41:01.224 [main] ERROR org.springframework.boot.SpringApplication - Application startup failed
org.springframework.beans.factory.BeanDefinitionStoreException: Failed to process import candidates for configuration class [my.testing.MyAppMain]; nested exception is java.lang.IllegalArgumentException: No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.
at org.springframework.context.annotation.ConfigurationClassParser.processDeferredImportSelectors(ConfigurationClassParser.java:482)
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:184)
...
It looks like it didn't found auto configuration classes in META-INF/spring.factories.
How to add this file? And what should be the content of it?
I've got following build script:
apply plugin: "java";
apply plugin: "idea";
apply plugin: 'application'
apply plugin: 'eu.appsatori.fatjar'
apply plugin: 'org.springframework.boot'
repositories {
mavenCentral()
}
buildscript {
ext {
springBootVersion = '1.4.3.RELEASE'
}
repositories {
mavenCentral()
jcenter()
}
dependencies {
classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}"
classpath "eu.appsatori:gradle-fatjar-plugin:0.3"
}
}
sourceSets {
main {
java {
srcDir 'src/main/java'
}
resources {
srcDir 'src/main/resources'
}
}
test {
java {
srcDir 'src/test/java'
}
}
}
fatJar {
manifest {
attributes("Main-Class": 'my.testing.MyAppMain')
}
exclude 'META-INF/*.DSA'
exclude 'META-INF/*.SF'
exclude 'META-INF/*.RSA'
}
dependencies {
compile 'org.springframework.boot:spring-boot-starter-jdbc'
runtime 'mysql:mysql-connector-java'
testCompile 'org.springframework.boot:spring-boot-starter-test'
}
And my example code is:
package my.testing;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
#SpringBootApplication
public class MyAppMain {
private ConfigurableApplicationContext springContext;
#Autowired
private SimpleDao dao;
public static void main(String[] args) throws Exception {
MyAppMain test = new MyAppMain();
try {
test.init();
test.doWhatYouGotToDo();
} finally {
test.stop();
}
}
private void doWhatYouGotToDo() {
System.out.println("Auto-wired dao: " + dao.hashCode());
System.out.println("Auto-wired jdbcTemplate: " + dao.jdbcTemplate.hashCode());
}
private void init() throws Exception {
springContext = SpringApplication.run(MyAppMain.class);
springContext.getAutowireCapableBeanFactory().autowireBean(this);
}
private void stop() throws Exception {
springContext.close();
}
}
#Component
class SimpleDao {
#Autowired
JdbcTemplate jdbcTemplate;
}
application.properties file:
spring.datasource.driver-class-name = com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://localhost:3306/some_db?useSSL=false&serverTimezone=UTC
spring.datasource.username = some_user
spring.datasource.password = some_pass
NOTE: This question is based on SpringBoot - making jar files - No auto configuration classes found in META-INF/spring.factories
where are all answers are referring to building with Maven. Please put only answers related to Gradle here.
Although I mostly use Maven for Spring and Gradle for Android, but here is the gradle way for a Spring project:
gradle clean build
gradle bootRepackage
Result:
Here is my build.gradle file:

Resources