-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
getting 'bazel-springboot-rule' working
- Loading branch information
1 parent
8c5af99
commit dc7d2c6
Showing
12 changed files
with
1,001 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# | ||
# Copyright (c) 2017-9, salesforce.com, inc. | ||
# All rights reserved. | ||
# Licensed under the BSD 3-Clause license. | ||
# For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause | ||
# | ||
|
||
# Spring Boot Packager | ||
# (implemented by Salesforce) | ||
|
||
# See the README.md file for detailed usage instructions. | ||
|
||
exports_files(["springboot.bzl", "springboot_pkg.sh", "verify_conflict.py", "write_gitinfo_properties.sh", "write_manifest.sh", "whitelist.txt"]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
## SpringBoot Rule | ||
|
||
This implements a Bazel rule for packaging a Spring Boot application as an executable jar file. | ||
The output of this rule is a jar file that can be copied to production environments and run. | ||
|
||
## How to Use: | ||
|
||
### Create your BUILD file | ||
|
||
This is a *BUILD* file code snippet of how to invoke the rule: | ||
|
||
``` | ||
# load our Spring Boot rule | ||
load("//tools/springboot:springboot.bzl", "springboot",) | ||
# create our deps list for Spring Boot, we have some convenience targets for this | ||
springboot_deps = [ | ||
"//tools/springboot/import_bundles:springboot_required_deps", | ||
"//tools/springboot/import_bundles:springboot_jetty_starter_deps", | ||
"//tools/springboot/import_bundles:springboot_web_starter_deps", | ||
] | ||
# this Java library contains your service code | ||
java_library( | ||
name = 'helloworld_lib', | ||
srcs = glob(["src/main/java/**/*.java"]), | ||
resources = glob(["src/main/resources/**"]), | ||
deps = springboot_deps, | ||
) | ||
# use the springboot rule to build the app as a Spring Boot executable jar | ||
springboot( | ||
name = "helloworld", | ||
boot_app_class = "com.sample.SampleMain", | ||
java_library = ":helloworld_lib", | ||
deps = springboot_deps, | ||
) | ||
``` | ||
|
||
The *springboot* rule properties are as follows: | ||
|
||
- name: name of your application; the convention is to use the same name as the enclosing folder (i.e. the Bazel package name) | ||
- boot_app_class: the classname (java package+type) of the @SpringBootApplication class in your app | ||
- java_library: the library containing your service code | ||
- deps: list of jar file dependencies to add (these get packages as *BOOT-INF/lib* inside the executable jar) | ||
|
||
### Convenience Import Bundles | ||
|
||
The [//tools/springboot/import_bundles](import_bundles) package contains some useful bundles of imports. | ||
There are bundles for the Spring Boot framework, as well as bundles for the various starters. | ||
|
||
Since Spring Boot apps all need similar groups of dependencies, prefer to create/curate those import bundles if a | ||
dependency is coming as a transitive for a Spring Boot class. | ||
|
||
### Manage External Dependencies in your WORKSPACE | ||
|
||
This repository has an example [WORKSPACE](../../external_deps.bzl) file that lists necessary and some optional Spring Boot dependencies. | ||
These will come from a Nexus/Artifactory repository, or Maven Central. | ||
Because the version of each dependency needs to be explicitly defined, it is left for you to review and add to your *WORKSPACE* file. | ||
|
||
## Build and Run | ||
|
||
After installing the rule into your workspace at *tools/springboot*, you are ready to build. | ||
Add the rule invocation to your Spring Boot application *BUILD* file as shown above. | ||
You will then need to follow an iterative process, adding external dependencies to your *BUILD* and *WORKSPACE* files until it builds and runs. | ||
|
||
The build will run and create an executable jar file in the *bazel-bin* directory. | ||
Find it in the output directories, and then run it: | ||
|
||
``` | ||
bazel run //samples/helloworld | ||
``` | ||
|
||
In production environments, you will likely not have Bazel installed nor the Bazel workspace files. | ||
This is the primary use case for the executable jar file. | ||
Run the jar file locally using *java* like so: | ||
|
||
``` | ||
java -jar bazel-bin/samples/helloworld/helloworld.jar | ||
``` | ||
|
||
The executable jar file is ready to be copied to your production environment. | ||
|
||
## In Depth | ||
|
||
To understand how this rule works, start by reading the [springboot.bzl file](springboot.bzl). | ||
|
||
### Build Stamping of the Spring Boot jar | ||
|
||
Spring Boot has a nice feature that can display Git coordinates for your built service in the | ||
[/actuator/info](https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html#production-ready-endpoints) webadmin endpoint. | ||
If you are interested in this feature, it is supported by this *springboot* rule. | ||
However, to avoid breaking Bazel remote caching, we generally have this feature disabled for most builds. | ||
See the [//tools/buildstamp](../buildstamp) package for more details. | ||
|
||
### Duplicate Classes Detection | ||
|
||
We find that Spring Boot jars aggregate a great number of dependency jars, many from outside our Bazel | ||
build (external Maven-built jars). | ||
We have had cases where multiple jars brought in the same class, but at different versions. | ||
These are difficult to diagnose. | ||
|
||
There is a feature on the *springboot* rule that will fail the build if duplicate classes are detected: | ||
|
||
``` | ||
# use the springboot rule to build the app as a Spring Boot executable jar | ||
springboot( | ||
name = "helloworld", | ||
boot_app_class = "com.sample.SampleMain", | ||
java_library = ":helloworld_lib", | ||
deps = springboot_deps, | ||
fail_on_duplicate_classes = True, | ||
) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
# | ||
# Copyright (c) 2017-9, salesforce.com, inc. | ||
# All rights reserved. | ||
# Licensed under the BSD 3-Clause license. | ||
# For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause | ||
# | ||
|
||
# List of standard imports bundles that tend to be used together in Spring Boot. | ||
# Please create/curate new bundles and contribute back to the community. Thanks! | ||
|
||
|
||
java_import( | ||
name = 'springboot_required_deps', | ||
jars = [], | ||
exports = [ | ||
"@javax_servlet_javax_servlet_api//jar", | ||
"@org_springframework_spring_aop//jar", | ||
"@org_springframework_spring_beans//jar", | ||
"@org_springframework_spring_context//jar", | ||
"@org_springframework_spring_core//jar", | ||
"@org_springframework_spring_expression//jar", | ||
"@org_springframework_spring_web//jar", | ||
"@org_springframework_boot_spring_boot_actuator//jar", | ||
"@org_springframework_boot_spring_boot_actuator_autoconfigure//jar", | ||
"@org_springframework_boot_spring_boot//jar", | ||
"@org_springframework_boot_spring_boot_autoconfigure//jar", | ||
"@org_springframework_boot_spring_boot_loader//jar", | ||
"@org_springframework_boot_spring_boot_starter//jar", | ||
"@org_springframework_boot_spring_boot_starter_logging//jar", | ||
"@javax_annotation_javax_annotation_api//jar", | ||
], | ||
visibility = ["//visibility:public"], | ||
) | ||
|
||
java_import( | ||
name = 'springboot_jetty_starter_deps', | ||
jars = [], | ||
exports = [ | ||
"@org_springframework_boot_spring_boot_starter_jetty//jar", | ||
"@org_eclipse_jetty_jetty_http//jar", | ||
"@org_eclipse_jetty_jetty_io//jar", | ||
"@org_eclipse_jetty_jetty_security//jar", | ||
"@org_eclipse_jetty_jetty_server//jar", | ||
"@org_eclipse_jetty_jetty_servlet//jar", | ||
"@org_eclipse_jetty_jetty_util//jar", | ||
"@org_eclipse_jetty_jetty_webapp//jar", | ||
], | ||
visibility = ["//visibility:public"], | ||
) | ||
|
||
java_import( | ||
name = 'springboot_web_starter_deps', | ||
jars = [], | ||
exports = [ | ||
":springboot_logging_deps", | ||
":springboot_jackson_deps", | ||
"@org_springframework_boot_spring_boot_starter_web//jar", | ||
"@org_springframework_spring_web//jar", | ||
"@org_springframework_spring_webmvc//jar", | ||
"@org_eclipse_jetty_jetty_server//jar", | ||
"@org_eclipse_jetty_jetty_servlet//jar", | ||
"@org_eclipse_jetty_jetty_util//jar", | ||
"@org_eclipse_jetty_jetty_webapp//jar", | ||
], | ||
visibility = ["//visibility:public"], | ||
) | ||
|
||
java_import( | ||
name = 'springboot_logging_deps', | ||
jars = [], | ||
exports = [ | ||
"@ch_qos_logback_logback_classic//jar", | ||
"@ch_qos_logback_logback_core//jar", | ||
"@commons_logging_commons_logging//jar", | ||
"@org_slf4j_slf4j_api//jar", | ||
"@org_apache_logging_log4j_log4j_to_slf4j//jar", | ||
"@org_apache_logging_log4j_log4j_api//jar", | ||
"@org_slf4j_jul_to_slf4j//jar", | ||
"@org_jboss_logging_jboss_logging//jar", | ||
"@com_fasterxml_classmate//jar", | ||
], | ||
visibility = ["//visibility:public"], | ||
) | ||
|
||
java_import( | ||
name = 'springboot_jackson_deps', | ||
jars = [], | ||
exports = [ | ||
"@com_fasterxml_jackson_core_jackson_databind//jar", | ||
"@com_fasterxml_jackson_core_jackson_annotations//jar", | ||
"@com_fasterxml_jackson_core_jackson_core//jar", | ||
"@com_fasterxml_jackson_datatype_jackson_datatype_jdk8//jar", | ||
"@com_fasterxml_jackson_datatype_jackson_datatype_jsr310//jar", | ||
"@com_fasterxml_jackson_module_jackson_module_parameter_names//jar", | ||
], | ||
visibility = ["//visibility:public"], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
## Import Bundles for Spring Boot Starters | ||
|
||
This is a scheme for providing convenience bundles of dependencies for each | ||
open source Spring Boot starter. | ||
The intent of this package is to provide rule users with a single dep target for each | ||
Spring Boot starter you include, and one dep target for the base Spring Boot framework. | ||
|
||
In the following example, our dep list for the application includes the Spring Boot framework | ||
and two starters: | ||
|
||
``` | ||
springboot_deps = [ | ||
"//tools/springboot/import_bundles:springboot_required_deps", | ||
"//tools/springboot/import_bundles:springboot_jetty_starter_deps", | ||
"//tools/springboot/import_bundles:springboot_web_starter_deps", | ||
] | ||
``` | ||
|
||
### Open Source Starters | ||
|
||
There are about 50 open source starters supported by the Spring Boot team, and others in the wild | ||
supported by other teams. | ||
|
||
- [Official Starters](https://github.com/spring-projects/spring-boot/tree/master/spring-boot-project/spring-boot-starters) | ||
|
||
At this time, only a few starters are populated in the package. | ||
It is an open work item to improve that situation. | ||
|
||
### Improving this Feature | ||
|
||
For reasons explained in the issue linked below, internally at Salesforce this is not a complex problem. | ||
We have some constraints that eliminate much of the complexity. | ||
Solving this correctly in the public open source repository will take some effort. | ||
|
||
Review the details in this issue: | ||
|
||
- [Implement a stronger dependency bundling system for Spring Boot starters](https://github.com/salesforce/bazel-springboot-rule/issues/4) |
Oops, something went wrong.