8

I'm developing a Spring Boot application and I have to make it run in our Weblogic 12c server, as a war.

I try to find a way to pass the default Spring active profile (info here and here) to the application, without having to set an environment variable on the machine itself. I'd like to be able to specify this profile using the Weblogic admin console, if possible.

I tried playing with the "Environment / Servers / MyServer / Server Start / Arguments" options, but I've been unable to make Spring load the specified profile this way. I've tried, without success :

spring.profiles.active=dev
-Dspring.profiles.active='dev'
-Dspring.profiles.active=dev
-spring.profiles.active=dev
--spring.profiles.active=dev

Any idea if it's possible to pass the spring.profiles.active to Spring, using Weblogic? I need to pass "dev", "acc" or "prod".

UPDATE : I would accept an answer explaining any easy way to have different .properties files used for the application configurations, depending on the environment the Sprint Boot application runs on. Those .properties files could be bundled in the application itself, or can be external. But I need to touch the system Weblogic is running on at least as possible... No environment variables and ideally no change to the Weblogic files either! Ideally, the solution would involve some kind of manipulations done using the Weblogic Admin console, for example a way to pass a parameter representing the current environment to the Spring Boot application so the correct application.[ENVIRONMENT].properties file is used.

UPDATE 2 : One way of allowing each environment to have its own application.properties file , is by using Deployment plans. This is probably the recommended way of doing it. I'll add that as an answer, but I'd still prefere an easier approach... I can't believe it's not possible to simply pass a parameter to an application, when it's deployed in Weblogic! And what is the "Environment / Servers / MyServer / Server Start / Arguments option for if it can't be used for that purpose?

UPDATE 3 : Related thread. If I understand correctly, the "Environment / Servers / MyServer / Server Start / Arguments" options may only work if a NodeManager is enabled? That would explain why I'm unable to pass that spring.profiles.active=dev variable!

Community
  • 1
  • 1
electrotype
  • 8,342
  • 11
  • 59
  • 96

6 Answers6

4

Although Spring Profiles let us to populate the Spring Environment with the set of properties that belong to the same logical group named as profile, Spring Profiles is not the goal but one of the ways to achieve the goal.

The goal is to be able to populate the Spring Environment from externalized configuration, that is, the goal is to be able to deploy the same application code in different environments and load the specific configuration for each single environment.

Spring Boot offers a way to achieve that goal based on having an own PropertySource that designed to allow sensible overriding of values.

If you read http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config you will see that the profile-specific application properties is just one of the available sources of properties and that JNDI attributes will override the profile-specific properties.

Analyzing the Spring Boot properties overriding order (http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config) for JEE environments, the JNDI attributes take in fact the most precedence:

  1. I advise against using global settings, like global properties files, command line arguments, system environment variables, etc. because they are shared by all the applications deployed in the same application server.
    • You will get a collateral benefit: there is no need to modify Weblogic startup files
  2. ServletConfig and ServletContext init parameters aren't external configuration, to use them implies you have to package the application for each environment.

Note to activate a profile you must use global variable, so all the deployed applications in the same app server will activate the same profile.

So, in practice, in Spring Boot applications for pure JEE environments you have only two configuration sources:

  1. JNDI attributes
  2. Packaged application.properties

Note you should avoid the usage of packaged application-{profile}.properties files because profile activation means to activate the same profile in all the apps deployed in the same app server.

In that point you imagine the unique external configuration source you have in pure JEE* is JNDI.

[*] By "pure JEE" I mean without using external configuration servers like Spring Cloud Config (https://cloud.spring.io/spring-cloud-config/).

That said, the Weblogic deployment plans give you the easiest and comfortable way to load the JNDI attributes for each deployment and Spring Boot will populate the Spring Environment from JNDI.

The solution is really easy:

  1. Deploy your application and the Weblogic deployment plan customized for your environment (dev, pre, pro, ...)
  2. Use JNDI attributes values in your application as any other Spring Environment property: ${jndi.var} inside your application.properties, @Value(${jndi.var}), etc.
    • Note that Spring Boot will populate the Spring Environment with the JNDI attributes, so you will be able to use them in the same way you use the properties inside the application.properties file.

Hope it helps!

eruiz
  • 1,963
  • 1
  • 14
  • 22
  • Thanks for the help. Using a deployment plan is something I try to avoid, except if it can be automated in the Admin console. I'd like to simply deploy a .ear or a .war and then use the Admin console to specify the environment to use to the application. – electrotype Nov 15 '16 at 03:01
  • Also, I do not agree with *"Note you should avoid the usage of packaged application-{profile}.properties files because profile activation means to activate the same profile in all the apps deployed in the same app server."* : I was planning on having a *first* Spring active profile, which would have been the environment : "local", "dev", "acc", "prod". And then each application could *add* other active profiles, in there own application-{profile}.properties files. But the environment, the first active profile, would be shared by all the apps on that machine, and it's ok : it *is* the same env! – electrotype Nov 15 '16 at 03:05
  • It's too late to edit my first comment, but, to continue it : If it's possible to specify a `JNDI variable` for Spring, *using the Weblogic admin console only*, I'd like to know how! But I try to avoid having to provide a `plan.xml` file and having to create a special directory structure when I deploy the application. – electrotype Nov 15 '16 at 03:12
  • Well, I suppose we have different POVs about to set the active profile using global vars. In my environments an app server for DEV doesn't imply we have only one DEV profile. Although it is recommended to use the "dev" suffix for the profile DEV, each app could have its own DEV profile name: "development", "devel", etc. and all of these applications are deployed in the same app server for DEV environments. – eruiz Nov 15 '16 at 07:40
  • Weblogic doesn't provide a management tool for the JNDI server, so NO, you cannot use the _Weblogic admin console_ to manage the JNDI attributes. But it is really easy to manage the JNDI attributes: the project's _WEB-INF_ dir contains the _web.xml_ (that defines the JNDI attributes with the default values) plus one plan.xml for each env (plan-dev.xml, plan-pre.xml) that customizes the JNDI attributes for each env. When you upload the WAR using the _Weblogic admin console_ upload the needed _plan-{profile}.xml_ and that's all. – eruiz Nov 15 '16 at 07:48
3

You can set the active profiles using application.properties like below:

# PROFILES
spring.profiles.active= # Comma-separated list of active profiles.

As you have got multiple properties files packaged within the WAR (not recommended, rather dynamic properties to be extracted outside war), you can use @PropertySource(value = "classpath:application.dev.properties") to target a specific properties file to be used by the application.

You can look at here

Buhake Sindi
  • 87,898
  • 29
  • 167
  • 228
Vasu
  • 21,832
  • 11
  • 51
  • 67
  • Having a single `application.propeties` wouldn't help me since I need different configurations on different environments! The app needs to know on which environment it's running. I have multiple `properties` files : `application.dev.propeties`, `application.acc.propeties` and `application.prod.propeties`. I want to right one to be loaded... So the first active profile has to be defined *before* the properties file is loaded. – electrotype Nov 04 '16 at 18:13
  • Don't you have the properties files outside the application war/ear ? – Vasu Nov 04 '16 at 18:15
  • Not currently, they are embeded (I know : bad practice!). Where would you put those external `properties` files, if Weblogic is used, so the application can find them? – electrotype Nov 04 '16 at 18:17
  • Then how do you point your application currently to refer the right properties ? – Vasu Nov 04 '16 at 18:19
  • I'm currently working locally, with the `SPRING_PROFILES_ACTIVE` environment variable. But we can't use those on other environments. – electrotype Nov 04 '16 at 18:23
  • You can use @Configuration @PropertySource(value = "classpath:application.dev.properties") – Vasu Nov 04 '16 at 18:26
  • But *where * would you put the `application.properties` files, so there are in the classpath? Somewhere on the machine and then add this classpath to Weblogic using the `"Environment / Servers / MyServer / Server Start / Class Path"` option? I guess it would work. But for this project I would prefere Weblogic to simply pass the name of the profile to the app! Anyway, thanks for your inputs! – electrotype Nov 04 '16 at 18:33
  • Your edited example `@PropertySource(value = "classpath:application.dev.properties")` doesn't work though : it requires the app to know that the current environment is "dev". But how can it knows that? Again, its Weblogic that should tell the application which environment it is on... – electrotype Nov 04 '16 at 18:43
1

We use a similar way of working but with some major differences:

  • we pass a "DEPLOYMENT_ENV" property to WebLogic using the -D mechanism, this DEPLOYMENT_ENV defines the deployment environment (dev, test, acc, prod, ...)
  • this property is used inside the different Spring configuration mechanisms to load specific properties from the class path using an expression "classpath:configuration/${DEPLOYMENT_ENV}/some_property_filename.properties"
  • in JUnit testing we define the running mode value using @TestPropertySource
  • we DON'T use Spring profiles to make distinction of deployment environment but of running modes: default (for deployment under web container), test (in JUnit tests we use @ActiveProfiles), and some others... implying more important changes in the set of beans defined.

In my opinion trying to use Spring profiles for what you intend to, may lead to some subtle catch22 situations.

We prefer to use Spring profiles to make distinction of significant bean definition changes while using properties bound to deployment environment to make differences in the way these beans are configured.

p3consulting
  • 2,721
  • 2
  • 12
  • 10
  • 1
    How do you *"pass a "DEPLOYMENT_ENV" property to WebLogic using the -D mechanism"*? Do you have to edit a file on the server? Thanks for your inputs. – electrotype Nov 04 '16 at 19:00
  • Well, PROD/ACC/... deployments are handled by a specific team, they configure all servers according to a deployment manual that development teams have to supply them. – p3consulting Nov 05 '16 at 08:54
  • On DEV/TEST environment, developers just access the WebLogic console directly and may edit the startup script. Regarding the "deployment_env", the name of the variable itself is part of the deployment manual. – p3consulting Nov 05 '16 at 08:58
  • So the Weblogic installations have been *modified* so the "DEPLOYMENT_ENV" is passed to them when Weblogic start right? That or the "DEPLOYMENT_ENV" is set as environment variables on the machines... But I'm looking for a solution using an already installed Weblogic, without modifying its startup files... – electrotype Nov 05 '16 at 09:20
  • "modified" is the term I would use… ;) – p3consulting Nov 05 '16 at 16:35
  • In fact, here the WebLogic servers are configured to fit the needs of the applications… this includes JNDI datasources, JMS queues,… load balancing…, environment variables… etc. – p3consulting Nov 05 '16 at 16:40
1

I'll add this as an answer because it is a way of achieving what I'm trying to do, but I'll really prefere an easier approach. See the "UPDATE 2" part of my question...

This solution is to use Deployment Plans. This allows each environment to override resources from the applications, including the application.properties file.

electrotype
  • 8,342
  • 11
  • 59
  • 96
1

I know I might be a bit late but I have been battling with the same problem. Most of the answers provided don't really specify how to go about when your application has to be deployed to different environment servers. So after doing a little bit of digging up, here is what I discovered and did:

  1. Create an application.properties file with the following in it: spring.profiles.active=<env> where <env> is the environment you want your spring boot application to point at.
  2. Wrap it as a jar file using the following command:
jar -cf <env>-profile.jar application.properties
  1. Within your WebLogic server domain in there is a lib directory, upload the jar file you just created in that directory and restart the Weblogic server.

Repeat, changing the <env> environment, to make a jar for all the server environments you want to upload your Spring Boot application to point to. For example for test the application.properties file will have the following line in it: spring.profiles.active=test and the jar will be test-profile.jar

sephoro
  • 150
  • 10
0

After two days, I found a way to activate spring profiles during WebLogic deployment, which fits my needs. Used this as reference.

I have application.properties, application-dev.properties, application-test.properties, application-prod.properties in my resource directory.

In my application.properties file I have spring.profiles.active=${environment}

On my Linux server, where WebLogic server is installed, I have a environment variable included in the profile file. export environment=dev. If it is a windows os, you could also use environment variables. With this, it picked up the environment variable and activate profile during the initial application context and it would then consider application-dev.properties as the property file. Similarly for other environments.

Although some people suggested not to bundle all of the property files into the war file, not sure of the reason, but this a solution during initial testing process. I did not find the external property file much useful in my scenario, so I am going with this approach.