Friday Jan 16, 2015

Using the Oracle Public Maven Repository With ADF Applications

Apache Maven lovers, rejoice! Thanks to the Fusion Middleware team, Oracle now has a public repository for you to use! It is located at http://maven.oracle.com. The official Fusion Middleware documentation even contains a section on how to configure your environment to leverage it. While accurate, this documentation is fairly generic. My aim in this post is to explain you how to use the repository with ADF applications. I recorded a video demonstration as well.

I started to use Maven with ADF back in 2007, when the first technical previews for 11g were made public. I had used Maven on other Java projects before. I was the architect on a large software development project and wanted my team to implement a workflow build around continuous integration principles. At the time, JDeveloper didn't support Maven. Thus, we had to deploy our own internal repository. I wrote a tool to scan the JDeveloper extensions, extract the various JAR files and import them in the repository. Nowadays, this process is automated; you simply have to use the Maven Synchronization Plug-in.

JDeveloper is not only compatible with Maven, but it actually ships with it. This started with Maven 3.0.4 back in version 12.1.2. JDeveloper 12.1.3 brought small but significant improvements to Maven support, and updated the Maven version to 3.0.5. I strongly recommend you to use the Maven release that ships with JDeveloper, as the various Oracle plugins involved may not have been tested with later releases. You will be on your own if you do otherwise.

Let's now see in detail how to setup your environment in order to compile and deploy ADF applications with Maven from the command line.


Step 1: Register 

The repository may be public, but you need to register in order to access it. This is to ensure you have accepted the licence agreement for the artifacts it contains. You can register here: 

https://www.oracle.com/webapps/maven/register/license.html.

Every time you will access the repository, you will need to provide your OTN user name and password. 


Step 2: Create environment variables and alter the path. 

The Maven distribution bundled with JDeveloper is located in the following directory. 

JDEV_HOME/oracle_common/modules/org.apache.maven_<version>

You have to create two environment variables: M2_HOME, which must point to the directory above, and M2, which must be set to %M2_HOME%\bin on Windows or $M2_HOME/bin on Linux and OS X. You must add the M2 variable to the PATH as well. In addition, ensure JAVA_HOME exists and points to a valid Java install.

Once you are done, you may test your setup by executing the maven -version command on the command line. Below is the output I get on a Windows 8.1 machine. 

Microsoft Windows [Version 6.3.9600]
(c) 2013 Microsoft Corporation. All rights reserved.

C:\Users\Frédéric>mvn -version
Apache Maven 3.0.5 (r01de14724cdef164cd33c7c8c2fe155faf9602da; 2013-02-19 08:51:28-0500)
Maven home: C:\Oracle\jdev1213\oracle_common\modules\org.apache.maven_3.0.5
Java version: 1.7.0_60, vendor: Oracle Corporation
Java home: c:\Java64\jdk1.7.0_60\jre
Default locale: en_CA, platform encoding: Cp1252
OS name: "windows 8.1", version: "6.3", arch: "amd64", family: "windows"
C:\Users\Frédéric>


Step 3: Define the repository 

You must provide Maven the information it needs in order to connect the repository. This can be achieved by adding a repository definition either to your POM or to Maven's settings.xml file. Personally, I prefer to go the settings.xml route since such information will likely be shared among several applications.

Typically, setting.xml is found in the user's home directory under the .m2 subdirectory.  On my Windows machine, the full path is c:\users\Frédéric\.m2. The equivalent path would be /Users/Frédéric/.m2 under OS X. You can learn more about this file on the official Maven website

To ensure that the repository definitions contained in settings.xml will be available at runtime, they should reside in a profile marked as active by default. 

<profiles>
    <profile>
      <id>Oracle</id>
      <activation>
          <activeByDefault>true</activeByDefault>
      </activation>
      <repositories>
        ...
        </repository>
      </repositories>
      <pluginRepositories>
        ...
      </pluginRepositories>
    </profile>
</profiles>

The repository definition  must look like this:

<repositories>
    <repository>
      <id>maven.oracle.com</id>
      <releases>
        <enabled>true</enabled>
        <updatePolicy>never</updatePolicy>
      </releases>
      <snapshots>
        <enabled>false</enabled>
        <updatePolicy>never</updatePolicy>
      </snapshots>
      <url>https://maven.oracle.com</url>
      <layout>default</layout>
    </repository>
</repositories>
<pluginRepositories>
    <pluginRepository>
      <id>maven.oracle.com</id>
      <releases>
        <enabled>true</enabled>
      </releases>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
      <url>https://maven.oracle.com</url>
      <layout>default</layout>
    </pluginRepository>
</pluginRepositories>

Only releases are enabled, since Oracle will not deploy snapshots to the repository. In addition, I set the update policy to never since Oracle will not provide patches or other updates. New artifacts will be published for future releases of ADF, but you will have to explicitly reference the new version numbers in your POMs to pick them up. We did this for stability reasons.

The repository is defined twice; once as an artifact repository and once as a plugin repository. The latter is needed since the ojmake and ojdeploy plugins are needed in order to build ADF applications. Moreover, the WebLogic plugin might be required for runtime deployment. This distinction between artifact and plugin repositories has been introduced in Maven 3.


Step 4: Update Wagon-http 

Wagon-http is a component used by Maven to access remote repositories. The Oracle public Maven repository is protected by the same single sign-on (SSO) solution that other Oracle web sites use. Unfortunately, older versions of wagon-http are not compatible with such enterprise-grade infrastructures. However, it is possible to override the version that is bundled with Maven.

To use the Oracle repository, you will need wagon-http 2.8. Simply download the required JAR file from the following location:

 http://central.maven.org/maven2/org/apache/maven/wagon/wagon-http/2.8/wagon-http-2.8-shaded.jar

You will then need to copy the file to the M2_HOME\lib\ext directory. 

Please note that wagon-http 2.8 is included in Maven 3.2.5 and higher. Thus, this step will likely become unnecessary in the future, since new releases of JDeveloper will probably provide an even more recent build of Maven.  


Step 5:  Define the server

While is is possible to define repositories in the POM, certain settings must absolutely be defined in the settings.xml file. Here is how the server definition look like.

<server>
  <id>maven.oracle.com</id>
  <username>blueberry.coder@oracle.com</username>
  <password>{HsygnP77JNIHdWNRgDiuknhzqnt0NFtIpTlQ4jlwOGk=}</password>
  <configuration>
	<basicAuthScope>
	  <host>ANY</host>
	  <port>ANY</port>
	  <realm>OAM 11g</realm>
	</basicAuthScope>
	<httpConfiguration>
	  <all>
		<params>
		  <property>
			<name>http.protocol.allow-circular-redirects</name>
			<value>%b,true</value>
		  </property>
		</params>
	  </all>
	</httpConfiguration>
  </configuration>
</server>

 In theory, you could write your password in clear text and things would work. However, Oracle strongly recommends that you encrypt the password using the tools provided by Maven.


Step 6: Encrypt your password 

There are two tasks to perform in order to complete this step.

First, you must generate and store a master password. This password is used to encrypt other passwords and should not be the same used by your Oracle account. To generate it, open a command prompt and execute the following command:

mvn --encrypt-master-password <password>

This will give you back a string such as {RpmTqVoMD0kHBbAIe2Jq1vdcM8HuPb/uvdnO+R4c67g=}.You should then create a file called settings-security.xml in the same folder as the settings.xml file used by Maven. The contents of this file should look like this:

<settingsSecurity>
  <master>{RpmTqVoMD0kHBbAIe2Jq1vdcM8HuPb/uvdnO+R4c67g=}</master>
</settingsSecurity>

 Once you are done with the master password, you can encrypt the actual password for your account using the command below.

mvn --encrypt-password <password>

 Simply paste the string returned in the server definition that you created in step 5.


Step 7: Add the WebLogic plugin to your POM 

If you want to deploy your ADF application to WebLogic through Maven, you will need to reference the appropriate plugin in its top-level POM. 

<plugin>
    <artifactId>weblogic-maven-plugin</artifactId>
    <groupId>com.oracle.weblogic</groupId>
    <version>12.1.3-0-0</version>
    <configuration/>
    <executions>
        <execution>
            <id>wls-deploy</id>
            <phase>pre-integration-test</phase>
            <goals>
                <goal>deploy</goal>
            </goals>
            <configuration>
                <remote>false</remote>
                <adminurl>t3://127.0.0.1:7777</adminurl>
                <user>weblogic</user>
                <password>welcome1</password>
                <source>${basedir}/deploy/FullMavenTest_Project1_FullMavenTest.ear</source>
                <targets>DefaultServer</targets>
                <verbose>true</verbose>
                <name>${project.build.finalName}</name>
            </configuration>
        </execution>
    </executions>
</plugin>

In this example, the WLS administrative password has been specified in clear text. The userConfigFile and userKeyFile parameters make it possible to encrypt the password, however. In addition, the source parameter must point to the EAR produced by the build process. The name for that EAR is managed through JDeveloper settings, and not through the POM. Moreover, please note that the value for the targets parameter should be set to DefaultServer if you want to deploy to the JDeveloper integrated WLS instance.

The WebLogic plugin requires a specific JAR in the classpath in order to execute. This requirement can be fulfilled by adding this dependency to the POM:

<dependency>
    <groupId>com.oracle.weblogic</groupId>
    <artifactId>weblogic-classes</artifactId>
    <version>12.1.3-0-0</version>
    <scope>system</scope>
    <systemPath>${oracleHome}/wlserver/server/lib/weblogic-classes.jar</systemPath>
</dependency>

The systemPath parameter must be the absolute path to the weblogic-classes.jar file. 


Step 8: Update your JDBC settings

In the case you plan to deploy your ADF application to WebLogic using Maven, you need to change a specific JDBC setting using JDeveloper. The reason for this is that, normally, the IDE will regenerate the WLS JDBC descriptors at deployment time. Unfortunately, this results in an error message when deploying without JDeveloper, whether through the command line or the WLS console. The specific error message is: « No credential mapper entry found for password indirection »

To avoid this, create a JDBC datasource on the WLS server and uncheck the following setting in the Application Properties dialog. 

Please note that defining a credential mapping using the WLS console will not work.  

If you have deployed the application from JDeveloper before, you will need to delete the generated weblogic-jdbc.xml and remove the reference to it inside the weblogic-application.xml descriptor. You will find both files under the src/META-INF subdirectory of the application workspace.


Step 9: Let's do this!

You are now ready to compile and deploy your application. You can do so on the command line only for the time being. Moreover, you will need to specify a value for the ORACLE_HOME environment variable, since this is normally something JDeveloper will do for you. Here is an example:

mvn pre-integration-test -Denv.ORACLE_HOME=c:\Oracle\jdev1213

 Just remember to make sure the JDeveloper integrated WLS instance is running before starting the build process if you want to deploy on it.

At this time, it is not possible to index the contents of the Oracle public repository. We will need to update JDeveloper in order to make this possible. 

Monday Jun 30, 2014

JDeveloper 12.1.3 is good news for Maven fans

JDeveloper 12c 12.1.3 is finally available. The list of new features and enhancements is quite impressive. Have a look! You will not be disappointed. Personally, I was very happy to discover than Apache Maven support has been enhanced in two small but critical areas: paths and archetypes. Don't get me wrong: Maven support in 12.1.2 is leaps and bounds ahead what 11g offers. But the tweaks brought in 12.1.3 make a significant difference. 

The main issue with the Maven support in 12.1.2 is that the POM files generated by JDeveloper contain absolute paths. This is problematic, since applications will not compile correctly unless the code resides in the same location on all developer workstations and build servers. This is not always possible or even desirable. Thus, I described how to replace those absolute paths with relative ones in a previous blog post. Fortunately, JDeveloper 12.1.3 does things differently and writes its POMs with relative paths instead. 

Maven archetypes help developers create new applications from scratch  from the command line. It is now possible to build a new ADF application that way using the oracle-adffaces-ejb archetype introduced by Oracle in JDeveloper 12.1.3. The resulting application will use EJB for its model layer. To use the archetype, simply issue a command like the one below:

mvn archetype:generate
 -DarchetypeGroupId=com.oracle.adf.archetype
 -DarchetypeArtifactId=oracle-adffaces-ejb
 -DarchetypeVersion=12.1.3-0-0
 -DgroupId=oracle.test
 -DartifactId=my-maven-test
 -Dversion=1.0-SNAPSHOT

 Obviously, this command will be successful only if the Maven binaries directory has been added to the path. Remember that Maven is provided by JDeveloper and can be found in the ORACLE_HOME/oracle_common/modules directory - although you can use your own install instead.

 If you prefer to use a GUI, you can create an application from inside JDeveloper by using a little known option introduced in 12.1.2. First, open the New... gallery and select the Maven subcategory (under the General category). Then, select the Generate from Archetype item.

This will bring up the dialog shown below.

Fill the various values per Maven conventions. The application top level directory will be created under the directory you specify. To select the archetype to use, click on the looking glass besides the Maven archetype field. JDeveloper will then display the Search for Archetypes dialog. To use it, simply type a search string and press Enter. JDeveloper will list all the matching archetypes available for the repositories selected.

Simply select the appropriate archetype and click on OK to create the new application. 

Depending how your environment has been setup, it is possible that your local Maven repository doesn't contain an archetype catalog. If that's the case, the Local Repository option will be grayed out in the Search for Archetypes dialog. To fix this, execute the command below. 

mvn archetype:crawl -Dcatalog=<maven directory folder>/archetype-catalog.xml 

 On Linux and OS X, the local repository is usually found at $HOME/.m2.  On Windows, the default location is %HOMEDRIVE%%HOMEPATH%/.m2. 

Monday Jul 29, 2013

JDeveloper 12c and Maven: Using relative paths in your POM files

One of the greatest things about JDeveloper 12c is the significantly improved support for Apache Maven. By default, the POM files produced by my favorite IDE contain some absolute paths, such as the folder for the ojmake/ojdeploy executables and references to project (.jpr) and application (.jws) files. Here is a sample of such paths extracted from an application I created on a Windows machine.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
      <plugin>
        <groupId>com.oracle.adf.plugin</groupId>
        <artifactId>ojmake</artifactId>
        <version>12.1.2-0-0</version>
        <configuration>
          <ojmake>
            C:\Oracle\Middleware1212\jdeveloper\jdev\bin\ojmake.exe
          </ojmake>
          <files>
            C:\OracleData\JDEV_USER_DIR\mywork\MavenTest\Model\Model.jpr
          </files>
          <usemaven>
            true
          </usemaven>
        </configuration>
        <executions>
          <execution>
            <phase>compile</phase>
            <goals>
              <goal>compile</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

This is perfectly fine if your development team uses workstations that are configured in a consistent way and run under the same operating system. It is often not the case in the real world. Fortunately, Maven provides features that make it very easy to use relative paths instead.

The first thing you should know is that Maven supports the use of variables in POM files. Those variables are always referenced using the following syntax:

${variable_name}

There are several built-in variables provided by Maven. One of them is ${basedir}, which points to the folder where the current POM is located. In addition, Maven can access any environment variable defined by the operating system. This is achieved though the following syntax:

${env.variable_name}

 Thus, it is possible to remove all absolute paths from the sample above by using ${basedir} and referencing an environment variable. Suppose I created such a variable named OJ_HOME, which points to  C:\Oracle\Middleware1212\jdeveloper\jdev\bin. Then, the POM would look like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
      <plugin>
        <groupId>com.oracle.adf.plugin</groupId>
        <artifactId>ojmake</artifactId>
        <version>12.1.2-0-0</version>
        <configuration>
          <ojmake>
            ${env.OJ_HOME}\ojmake.exe
          </ojmake>
          <files>
            ${basedir}\ViewController.jpr
          </files>
          <usemaven>
            true
          </usemaven>
        </configuration>
        <executions>
          <execution>
            <phase>compile</phase>
            <goals>
              <goal>compile</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

This POM will run on any workstation, granted the OJ_HOME variable is set to a suitable value.

About

Frédéric Desbiens

The musings of a member of the Mobility and Development Tools Product Management team.

I focus here on my favorite development frameworks, namely Oracle ADF and the Oracle Mobile Application Framework (MAF), but also have a strong interest in SOA and web services.

The views expressed on this blog are my own and do not necessarily reflect the views of Oracle.

Search

Archives
« August 2015
SunMonTueWedThuFriSat
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
     
Today