salesforce / rules_spring

Bazel rule for building Spring Boot apps as a deployable jar
BSD 3-Clause "New" or "Revised" License
224 stars 48 forks source link

Spring Cloud example #132

Closed geaden closed 3 years ago

geaden commented 3 years ago

I'd appreciate if you give an example on how to incorporate Spring Cloud dependencies.

I have in my WORKSPACE:

_GCP_VERSION = "1.2.8.RELEASE"
_SPRING_DATA = "2.4.4"
maven_install(
    name = "spring_cloud",
    artifacts = [
        "org.springframework.data:spring-data-commons:{}".format(_SPRING_DATA),
        "org.springframework.cloud:spring-cloud-gcp-starter-data-datastore:{}".format(_GCP_VERSION),
    ],
    repositories = [
        "https://repo1.maven.org/maven2",
    ],
    fetch_sources = True,
)

And use as dependency in BUILD file:

deps = [
    ...

    # Spring Cloud
    "@spring_cloud//:org_springframework_cloud_spring_cloud_gcp_starter_data_datastore",
]

However, application fails to start with exception.

Exception

```java java.lang.IllegalStateException: ConfigFileApplicationListener [org.springframework.boot.context.config.ConfigFileApplicationListener] is deprecated and can only be used as an EnvironmentPostProcessor at org.springframework.boot.context.config.ConfigFileApplicationListener.onApplicationEvent(ConfigFileApplicationListener.java:198) at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172) at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165) at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139) at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:127) at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:82) at org.springframework.boot.SpringApplicationRunListeners.lambda$environmentPrepared$2(SpringApplicationRunListeners.java:63) at java.base/java.util.ArrayList.forEach(ArrayList.java:1541) at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:117) at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:111) at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:62) at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:362) at org.springframework.boot.SpringApplication.run(SpringApplication.java:320) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1309) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1298) at com.samples.SampleMainKt.main(SampleMain.kt:23) ```

Would be great to have an example on how to make it work.

Thanks in advance!

plaird commented 3 years ago

I am not quite sure how to guide you with just the above. I think the best way to get started is to use the Spring Initializer to generate a Maven app with the features you need. Once you have that application working as you like, if you then publish it to a Git repo, I can guide in you porting that to Bazel.

geaden commented 3 years ago

Thanks! This was very wise advice. It turned out I had to use

"com.google.cloud:spring-cloud-gcp-starter-data-datastore"

instead of

"org.springframework.cloud:spring-cloud-gcp-starter-data-datastore"

with a bunch other com.google.cloud:* dependencies. I now able to run my app.

However, it seems if app is not at the top level of WORKSPACE, file application.properties is added to jar as: classes/path/to/app/resources/application.properties and Spring Boot doesn't use it. I suppose it expects classes/application.properties location.

Any ideas on how to make application.properties visible?

I have the following layout for my app:

/path/to/app
├── BUILD
├── kotlin
│   └── com
│       └── samples
│           └── SampleMain.kt
└── resources
    └── application.properties

And my BUILD file:

BUILD ```python load("@rules_spring//springboot:springboot.bzl", "springboot") load("@io_bazel_rules_kotlin//kotlin:rules.bzl", "kt_jvm_library") kt_jvm_library( name = "kotlinapplib", srcs = glob(["kotlin/**/*.kt"]), resources = glob(["resources/**/*"]), runtime_deps = runtime_deps, deps = deps, ) springboot( name = "kotlinapp", boot_app_class = "com.samples.SampleMainKt", fail_on_duplicate_classes = False, java_library = ":kotlinapplib", deps = deps + runtime_deps , ) ```

Thanks!

geaden commented 3 years ago

Apparently, this can be fixed with resources_strip_prefix:

kt_jvm_library(
  ...
  resources_strip_prefix = "/path/to/app/resources",
  ...
)

After that appliction.properties is seen.

Thanks! And sorry for disturbance.

I'm closing the issue.

plaird commented 3 years ago

OK, glad you found a solution. I experimented with this, and I updated the kotlin example to use properties.

https://github.com/salesforce/rules_spring/commit/b5d298e7ef07545555ff6022c5faf8544d0fa612