Deploy Spring boot gradle app in Google App Engine - java

I have searched for the tutorial to deploy Spring boot application using Gradle. I failed to find any resource that explains the process to do so.
Can anyone guide me the process?
My project works like a charm when its run locally on my machine. But I would like to deploy on the Google app engine's Flexible Java Environment.
Thanks, in advance.
My build.gradle looks like this
buildscript {
ext {
springBootVersion = '2.0.4.RELEASE'
jwtVersion = '3.4.0'
appEngineVersion = '1.9.56'
appEngineGradleToolsVersion = '1.3.4'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'com.example'
version = '0.0.1'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile('org.springframework.boot:spring-boot-starter-actuator')
compile('org.springframework.boot:spring-boot-starter-web')
compile('org.springframework.boot:spring-boot-starter-thymeleaf')
compile("org.springframework.boot:spring-boot-starter-security")
// JPA Data (We are going to use Repositories, Entities, Hibernate, etc...)
compile 'org.springframework.boot:spring-boot-starter-data-jpa'
// Use MySQL Connector-J
compile 'mysql:mysql-connector-java'
implementation "com.auth0:java-jwt:${jwtVersion}"
runtime('org.springframework.boot:spring-boot-devtools')
testCompile('org.springframework.boot:spring-boot-starter-test')
}

Spring Boot for Google App Engine Standard (Java 8)
This sample demonstrates how to deploy a Spring Boot application on Google App Engine.
See the Google App Engine standard - documentation for more detailed instructions.
See the Using Cloud SQL for MySQL for working with mysql
Java 8
Maven (at least 3.5)
Google Cloud SDK (aka gcloud command line tool)
Setup
Download and initialize the Cloud SDK
gcloud init
Create an App Engine app within the current Google Cloud Project
gcloud app create
Maven
Running locally
mvn appengine:run
To use vist: http://localhost:8080/
Deploying
mvn appengine:deploy
To use vist: https://YOUR-PROJECT-ID.appspot.com
Testing
mvn verify
As you add / modify the source code (src/main/java/...) it's very useful to add unit testing
to (src/main/test/...). The following resources are quite useful:
Junit4
Mockito
Truth
For further information, consult the
Java App Engine documentation.
Steps to convert a Spring Boot application for App Engine Standard
Use the WAR packaging
You must use WAR packaging to deploy into Google App Engine Standard.
If you generate a Spring Boot project from start.spring.io,
make sure you switch to the full version view of the initializer site, and select WAR
packaging.
If you have an existing JAR packaging project, you can convert it into a WAR project by:
1. In pom.xml, change <packaging>jar</packaging> to <packaging>war</packaging>
1. Create a new SpringBootServletInitializer implementation:
public class ServletInitializer extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(YourApplication.class);
}
}
Remove Tomcat Starter
Google App Engine Standard deploys your WAR into a Jetty server. Spring Boot's starter
includes Tomcat by default. This will introduce conflicts. Exclude Tomcat dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
Do not include the Jetty dependencies. But you must include Servlet API dependency:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
Add App Engine Standard Plugin
In the pom.xml, add the App Engine Standard plugin:
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>appengine-maven-plugin</artifactId>
<version>1.3.1</version>
</plugin>
This plugin is used to run local development server as well as deploying the application
into Google App Engine.
Add App Engine Configuration
Add a src/main/webapp/WEB-INF/appengine-web.xml:
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<version>1</version>
<threadsafe>true</threadsafe>
<runtime>java8</runtime>
</appengine-web-app>
This configure is required for applications running in Google App Engine.
Exclude JUL to SLF4J Bridge
Spring Boot's default logging bridge conflicts with Jetty's logging system.
To be able to capture the Spring Boot startup logs, you need to exclude
org.slf4j:jul-to-slf4j dependency. The easiest way to do this is to
set the dependency scope to provided, so that it won't be included in
the WAR file:
<!-- Exclude any jul-to-slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<scope>provided</scope>
</dependency>
Out of memory errors
With Spring Boot >= 1.5.6, you may run into out of memory errors on startup.
Please follow these instructions to work around this issue:
Inside src/main/resources, adding a logging.properties file with:
.level = INFO
Inside src/main/webapp/WEB-INF/appengine-web.xml, add a config that points to the new logging.properties file.
<system-properties>
<property name="java.util.logging.config.file" value="WEB-INF/classes/logging.properties"/>
</system-properties>

Related

jaxws not compatible with javafx modules?

I have an java project with javafx and jaxws. Here a small snippelt from my gradle:
dependencies {
implementation 'com.sun.xml.ws:jaxws-ri:4.0.0'
}
javafx {
version = "19"
modules = [ 'javafx.controls', 'javafx.fxml' ]
}
task runClient(type: JavaExec) {
description = 'Run Client'
classpath = sourceSets.main.runtimeClasspath
jvmArgs = ['--module-path', classpath.asPath, '--add-modules', 'javafx.controls,javafx.fxml']
main = 'ClientMain'
}
I set this jvmArgs because of How to include plugin dependencies in JavaExec task classpath?. I don't actually use modules otherwise in my project.
I now get the error:
Error occurred during initialization of boot layer
java.lang.module.FindException: Module format not recognized: C:\Users\MyName\.gradle\caches\modules-2\files-2.1\com.sun.xml.ws\release-documentation\4.0.0\5eb09d77be092684546352a35f315423d67e044b\release-documentation-4.0.0-docbook.zip
Without javafx or jaxws everything is working. Only together there seems to be problems. Any ideas?
You are using the wrong dependency for jaxws for your purposes. The difference in distributions is explained here:
What's the difference between jaxws-ri and jaxws-rt?
jaxws-ri contains zipped documentation which should not be part of a modular distribution.
These are dependencies you should be using (maven format, you will need to translate to gradle format):
<dependencies>
<dependency>
<groupId>jakarta.xml.ws</groupId>
<artifactId>jakarta.xml.ws-api</artifactId>
<version>4.0.0</version>
</dependency>
</dependencies>
<dependencies>
<dependency>
<groupId>com.sun.xml.ws</groupId>
<artifactId>jaxws-rt</artifactId>
<version>4.0.0</version>
<scope>runtime</scope>
</dependency>
</dependencies>
Additional background info
jaxws reference implementations are now maintained via the Eclipse foundation as jakarta XML services as part of Eclipse Metro.
The code should also use the jakarta package namespace as shown in the jakarta documentation.
This would also apply to module names if you provide a module-info.

How to merge gradle with maven

I imported a gradle project on my eclipse. (I am using Java 11.) I had codes which uses jakarta.xml libraries.
import jakarta.xml.soap.*;
For it to function, I added Maven dependencies for jaxws-rt:
<dependencies>
<dependency>
<groupId>com.sun.xml.ws</groupId>
<artifactId>jaxws-ri</artifactId>
<version>3.0.0-M3</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>jakarta.xml.ws</groupId>
<artifactId>jakarta.xml.ws-api</artifactId>
<version>2.3.3</version>
</dependency>
</dependencies>
But when I try to generate the build, it shows following error:
error: package jakarta.xml.soap does not exist
import jakarta.xml.soap.*;
If I refresh the project as a Maven project the gradle feature gets disabled. If I run it as a gradle project, the maven dependencies get disabled. Can you please suggest how to run the build?
Do not manage separate dependencies on two different build platforms.
You will want to choose either Maven or Gradle. Having two build systems will cause unnecessary duplicate work and still requires continued maintenance. Going down this path will require you to manage two separate build files that are identical in nature. Every dependency in your gradle config will also need to be added to your maven config.
Instead of trying to create a pom.xml for the Maven build, you will want to determine the Gradle equivalent for the libraries you want to pull.
compile group: 'com.sun.xml.ws', name: 'jaxws-ri', version: '3.0.0-M3', ext: 'pom'
compile group: 'jakarta.xml.ws', name: 'jakarta.xml.ws-api', version: '2.3.3'

Springboot create a library from my model and repository classes

I could not find a answer to this question so if there is I'm sorry for repeating question.
I have 4 springboot apps (MICRO SERVICES ??), we have our main CRM on Oracle database running on Apex. Now over time Ive been trying to break it up. So I created some spring-boot apps for example I have one that is for google services eg: geo codeding, place searching etc. I have one that is for connecting our CRM to Xero online accounting service API and 3rd one that is running web-socket server so we can push messages to users of Oracle Apex.
Now in all the projects I'm connecting to the same database so I have 4 copies of my Model and Repository classes.
What I would like to do is to create a jar that has them and then share it across the projects. Now I can create a library but as I need to have spring deps in the library.
I created this as my gradle.build
buildscript {
ext {
springBootVersion = '1.5.10.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
group = 'com.example'
version = '0.0.1'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile('org.springframework.boot:spring-boot-actuator-docs')
compile('org.springframework.boot:spring-boot-starter-actuator')
compile('org.springframework.boot:spring-boot-starter-data-jpa')
compile('org.springframework.boot:spring-boot-starter-data-rest')
compile('org.springframework.data:spring-data-rest-hal-browser')
runtime('org.springframework.boot:spring-boot-devtools')
compileOnly('org.springframework.boot:spring-boot-configuration-processor')
compileOnly('org.projectlombok:lombok')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
But I get a error if I don't have a application class with #SpringbootApplication annotation.
I'm sure I'm missing something but I need to create a jar library with spring JPARepositories.
Considering that you only want to use that library for your entities and repositories, you don't actually need Spring boot and can create a library using Spring only.
Just add the dependencies you need, in your case probably just spring-data-jpa (or alternatively, spring-boot-starter-data-jpa):
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
</dependency>
If you'd like to use the dependency management that Spring boot offers out of the box, you can still use it:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.5.7.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Now you can build it using the nomal Maven JAR plugin, rather than the Spring boot plugin.

Forcing maven spring boot project to use older version of a dependency instead of a new version from another dependency

I'm running in to a problem where I cannot start a spring boot server due to the same problem listed in this question:
How to set up Spring Boot and log4j2 properly?
I am encountering this scenario because the spring boot project has a dependency on a jar that includes elasticsearch, which includes a new version of slf4j that isn't compatible with spring boot
I tried the recommended solution by implementing every exclusion in the elasticsearch project dependency definition possible, but for some reason the new version keeps being picked up. I cannot seem to force the spring boot project to ignore the logging packages used by the elasticsearch project.
Here is my pom for the spring-boot project, see the dependency for problematic.project.import : http://pastebin.com/Yeq2qk9Y
Here is the pom for the project that is being imported into the spring boot project: http://pastebin.com/gknmf6Tt
The error I am getting is:
Caused by: java.lang.NoSuchMethodError: org.apache.logging.log4j.core.config.ConfigurationFactory.getConfiguration(Lorg/apache/logging/log4j/core/config/ConfigurationSource;)Lorg/apache/logging/log4j/core/config/Configuration;
at org.springframework.boot.logging.log4j2.Log4J2LoggingSystem.loadConfiguration(Log4J2LoggingSystem.java:165)
at org.springframework.boot.logging.log4j2.Log4J2LoggingSystem.loadDefaults(Log4J2LoggingSystem.java:148)
at org.springframework.boot.logging.AbstractLoggingSystem.initializeWithConventions(AbstractLoggingSystem.java:75)
at org.springframework.boot.logging.AbstractLoggingSystem.initialize(AbstractLoggingSystem.java:50)
Any tips on how to get this issue cleared? Is this possible for two versions of this set of libraries to be loaded, each module ignorant to the version they don't need?
You can exclude the cyclic dependencies by using the <exclusions> tag in your pom.xml like this:
<dependency>
<groupId>sample.ProjectB</groupId>
<artifactId>Project-B</artifactId>
<version>1.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>sample.ProjectE</groupId> <!-- Exclude Project-E from Project-B -->
<artifactId>Project-E</artifactId>
</exclusion>
</exclusions>
</dependency>
You should exclude the cyclic dependency of the newer version from the dependency which is having it and that way only the older version will be loaded and not both.
Here is the link for more information:
https://maven.apache.org/guides/introduction/introduction-to-optional-and-excludes-dependencies.html

Firebase in Google app engine throwing noMethodFound error while initialization

I am trying to initialize firebase in Google appengine web app and using maven for dependencies.
<dependency>
<groupId>com.google.firebase</groupId>
<artifactId>firebase-server-sdk</artifactId>
<version>[3.0.0,)</version>
</dependency>
Getting error
java.lang.NoSuchMethodError: com.google.api.client.googleapis.auth.oauth2.GoogleCredential.fromStream(....)
at com.google.firebase.FirebaseOptions$Builder.setServiceAccount(FirebaseOptions.java:77)
How to solve this issue:
Go to http://search.maven.org/#search%7Cga%7C1%7Cgoogle-api-client and find the last version of com.google.api-client API.
Add the dependency on you project
<dependency>
<groupId>com.google.api-client</groupId>
<artifactId>google-api-client-assembly</artifactId>
<version>last version </version>
</dependency>
I do this on EJB project using netbeans and glassfish server, so I download the jar file of the last version com.google.api-client add it on Netbeans Libraries and glassfish libraries, then I compile the project and restart glassfish.

Categories

Resources