Home > Blockchain >  How to Give Environment Specific Variable in pom.xml?
How to Give Environment Specific Variable in pom.xml?

Time:06-19

I am using a plugin to generate soap service client code. My wsdl files are located at src/main/resources/wsdl/dev and src/main/resources/wsdl/prod folders. I have 2 profiles: application-dev.properties and appllication-prod.properties

I would like to change the <wsdlFile> tag value based on the active profile. I specified the parts with ${app.env} below that need to change dynamically. Is there any way to do that?

        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>jaxws-maven-plugin</artifactId>
            <version>2.6</version>
            
            <configuration>
                <wsdlDirectory>${project.basedir}/src/main/resources/wsdl/${app.env}</wsdlDirectory>
                <packageName>com.example.jwt.jwtdemo.dto.cmsapi</packageName>
                <wsdlFiles>
                    <wsdlFile>${project.basedir}/src/main/resources/${app.env}/wsdl/MyLoginService_1.wsdl</wsdlFile>
                    <wsdlFile>${project.basedir}/src/main/resources/${app.env}/wsdl/MyService_1.wsdl</wsdlFile>
                </wsdlFiles>
                <sourceDestDir>
                    ${project.basedir}/src/main/java
                </sourceDestDir>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>wsimport</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

CodePudding user response:

You have two profile-specific properties files.
Each one can define app.env correctly, which means the the <wsdlFile> tag value will change based on the active profile.

But you could also use OS environment variables.

Both options, however, are for when the app is starting, not dynamically during runtime.

CodePudding user response:

Spring profiles are mainly a runtime thing, whilst WSDL generation is usually only done during project compile/build time. I don't think you can read back the selected profile in maven, unless you specify in maven during the build which profile to use.

For that you can use profiles in your pom, see https://www.baeldung.com/spring-profiles#maven-profile

<profiles>
    <profile>
        <id>dev</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
            <spring.profiles.active>dev</spring.profiles.active>
        </properties>
    </profile>
    <profile>
        <id>prod</id>
        <properties>
            <spring.profiles.active>prod</spring.profiles.active>
        </properties>
    </profile>
</profiles>

You don't have to use the spring.profiles.active property if you don't want to switch to defining your spring profiles like this (see the baeldung link for other configuration options), but you can use this to define your WSDL location or the filename of your application-x.properties file.

You can either add your WSDL location ${app.env} as a property directly in these pom profiles, or the location of the properties file (for the following option below).

However if you want to keep that location value in your spring properties file (and not duplicate it to the pom), you can use the properties plugin to read these properties and use the values at maven build time: https://www.mojohaus.org/properties-maven-plugin/index.html

The properties loaded from files or URLs can be used to filter resources differently for different environments. Those using Spring's PropertyPlaceholderConfigurer can see how these goals can be useful. Note that the URL format accepts Spring's classpath: style pseudo-URL syntax.

Specifically: https://www.mojohaus.org/properties-maven-plugin/read-project-properties-mojo.html

The read-project-properties goal reads property files and URLs and stores the properties as project properties. It serves as an alternate to specifying properties in pom.xml. It is especially useful when making properties defined in a runtime resource available at build time.

An example setup with Springs countries demo, where i picked wsdl.location as the property that is stored in one of two properties files, which are loaded at build time:

Properties (note: none are added here)

  <properties>
     <!-- your normal project properties -->
  </properties>

Profiles pointing to the location of your application.properties files:

    <profiles>
        <profile>
            <id>prod</id>
            <properties>
                <application.properties.file>${project.basedir}/src/main/resources/test.properties</application.properties.file>
            </properties>
        </profile>
        <profile>
            <id>dev</id>
                <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <properties>
                <application.properties.file>${project.basedir}/src/main/resources/test2.properties</application.properties.file>
            </properties>
        </profile>
    </profiles>

Properties reader plugin: (you need a phase before compile, as that is when wsimport is usually executed)

            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>properties-maven-plugin</artifactId>
                <version>1.0.0</version>
                <executions>
                    <execution>
                        <phase>validate</phase>
                        <goals>
                            <goal>read-project-properties</goal>
                        </goals>
                        <configuration>
                            <files>
                                <file>${application.properties.file}</file>
                            </files>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

WSDL plugin:

                    <wsdlFiles>
                        <!--suppress MavenModelInspection : read via properties plugin -->
                        <wsdlFile>${wsdl.location}</wsdlFile>
                    </wsdlFiles>

Test file 1

wsdl.location=countries.wsdl

Test file 2

wsdl.location=countries2.wsdl

Output of mvn clean package -p prod, profile prod (wsdl exists)

[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ test ---
[INFO] 
[INFO] --- properties-maven-plugin:1.0.0:read-project-properties (default) @ test ---
[INFO] 
[INFO] --- jaxws-maven-plugin:2.6:wsimport (default) @ test ---
[INFO] Processing: file:/.../src/main/resources/countries.wsdl

Output of mvn clean package -p dev, profile dev (test wsdl that doesnt exist to showcase profile switchting working)

[ERROR] Failed to execute goal org.codehaus.mojo:jaxws-maven-plugin:2.6:wsimport (default) on project test: 'countries2.wsdl' not found. -> [Help 1]

But note that if you add profiles in the pom.xml and direclty specify the WSDL location there in a property, you don't need the added complexity of reading the properties files.

So if you are willing the move the WSDL location to your pom file instead of the properties files, this should be sufficient:

    <profiles>
        <profile>
            <id>dev</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <properties>
                <app.env>dev</app.env>
            </properties>
        </profile>
        <profile>
            <id>prod</id>
            <properties>
                <app.env>prod</app.env>
            </properties>
        </profile>
    </profiles>
  • Related