For some time already it is possible to use Maven with ADF also inside Oracle JDeveloper. In projects, especially bigger ones, you will think about a way to automate your deployments. With the help of Maven you can compile, package, test and deploy an EAR file as artifact to a weblogic server via plugins. However most people use jenkins or hudson for build automation to generate jobs for nightly builds or other ways to distribute deployments to different environments.

Scenario – Maven version in frontend

In the usecase I had at a customer I faced the challange to find a good way for defining and displaying versions, build numbers and deployment timestamp – all in the frontend. Not only should all information be visible in the frontend but it should also be possible to use the version to handle side-by-side deployment in weblogic server for a smooth rollout process.

Solution

To handle versions in an ADF application correctly, i had to create an MANIFEST.MF file. This will be my central configuration file to collect version, weblogic-version, build number and build timestamp. The first two things need to be set from developer from time to time – the version of an application is not incrementing with every build and the developer knows best how to handle increasements correctly. The other two informations (build number and build timestamp) are coming from the jenkins server and i need to include them in the manifest. The solution for this is the following:

  1. I used a template file for manifest with placeholders to replace the specific parts via maven with the help of jenkins variables (MANIFEST.MF.template)
    Created-By: v7 team
    Extension-Name: de.virtual7.application
    Specification-Version: 0.1.2
    Weblogic-Application-Version: 0.1.2
    Implementation-Version: #BUILD_NUMBER#
    Implementation-Date: #BUILD_TIME#
    1. the replaced manifest file should not be part of the source versioning system (here GIT) because jenkins modifies it with every build and will get dirty states. This can have side effects with pulling. So i added the MANIFEST.MF itself to .gitignore and only the MANIFEST.MF.template is part of GIT.
  2. I placed the MANIFEST.MF.template to /ViewController/src/META-INF/ and add the MANIFEST.MF to the deployment descriptor of the WAR and of the EAR
  3. I placed a plugin to the POM of the ViewController project to replace the placeholders and write the correct MANIFEST.MF file based on the template
                 <plugin>
                    <groupId>com.google.code.maven-replacer-plugin</groupId>
                    <artifactId>maven-replacer-plugin</artifactId>
                    <version>1.4.0</version>
                    <executions>
                        <execution>
                            <phase>process-sources</phase>
                            <goals>
                                <goal>replace</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <file>src/META-INF/MANIFEST.MF.template</file>
                        <outputFile>src/META-INF/MANIFEST.MF</outputFile>
                        <replacements>
                            <replacement>
                                <token>#BUILD_NUMBER#</token>
                                <value>${build.number}</value>
                            </replacement>
                            <replacement>
                                <token>#BUILD_TIME#</token>
                                <value>${build.id}</value>
                            </replacement>
                        </replacements>
                    </configuration>
                </plugin>
  4. I added parameters to the maven call in jenkins to pass parameters with it from jenkins environment
    clean install -Dbuild.number=${BUILD_NUMBER} -Dbuild.id=${BUILD_TIMESTAMP}

    Because of a current bug in jenkins you need to install a jenkins plugin called “Zentimestamp Plugin”. This gives you the environment variable of “BUILD_TIMESTAMP” and you can define a pattern for it

  5. I read out the manifest in a bean inside the application to display the informations to frontend. Here is an example to get the build timestamp and form it in a pretty pattern (BUG: you cannot set this pretty pattern directly in the Zentimestamp plugin because the parameter will be passed with ‘.’ and ‘:’ –> this will fail in maven execution):
       public String getBuildTime() {
            ExternalContext application = FacesContext.getCurrentInstance().getExternalContext();
            InputStream inputStream = application.getResourceAsStream("/META-INF/MANIFEST.MF");
            Manifest manifest;
            String time = "";
            String outputDate = null;
            try {
                manifest = new Manifest(inputStream);
    
                Attributes attributes = manifest.getMainAttributes();
                time = attributes.getValue("Implementation-Date");
    
                SimpleDateFormat sdf = new SimpleDateFormat("ddMMyyyyHHmm");
                Date date = sdf.parse(time);
    
                SimpleDateFormat sdf2 = new SimpleDateFormat("dd.MM.yyyy HH:mm");
                outputDate = sdf2.format(date);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ParseException e) {
                e.printStackTrace();
            }
    
            return outputDate != null ? outputDate : time;
        }

     

Because the MANIFEST is also part of the EAR descriptor and there exists an “Weblogic-Application-Version” entry, you can simply increase the version in the manifest file and redeploy the EAR to have side-by-side deployment working!

 

Hint: It would be even better to pass the version from the maven POM to the manifest via ${project.version}. Because of a bug in jdeveloper with dependencies via maven we need to define libraries via paths. That is why we cannot rename the jar files dynamically with the version information and prevents us from this option. I have a service request open – maybe with JDeveloper 12.2.1.3 😉