Lab 08
In this lab session you will be training advanced build system concepts, such as build lifcycle phases, artifact
sideloading, and accessing third party artifact repositories.
You will be working with the XoxInternals code, which is a full working Model & Controller implementation the TicTacToe
game (paraphrased as Xox, for the X's and the O's).
To clone the sources, use: git clone https://github.com/m5c/XoxInternals.git
Maven lifecycle
Maven has three built-in lifecycles, each consisting of phases. We're mostly interested in the default lifecycle, which allows building software from sources.
Build by calling lifecycle phases
- The maven command always expects a lifecycle phase as argument.
- For every phase provided, the entire lifecycle until that phase is executed.
- E.g.
mvn packagecommand will execute all default lifecycle phases until (and including) thepackagephase.
Your turn
- You will be working with a new project
XoxFrontend, which will call some of the functionality provided by the clonedXoxInternalsproject.- However it is important that we want to connect these two projects, using maven, NOT by copy-pasting code from one project to the other.
-
For a start, initialize a new repo, called
XoxFrontend, by using the maven archetype command:mvn archetype:generate \ -DgroupId=ca.uqam.info \ -DartifactId=XoxFrontend \ -DarchetypeArtifactId=maven-archetype-quickstart \ -DinteractiveMode=falseIf you're on windows, type the command in a single line, and omit the antislashes.
-
The command will produce a new maven project of the following structure:
- Next build the project. Do so by calling the maven default lifecycle phase that only translates all java files into class files,
without producing a jar.
- Inspect the
targetfolder. Verify there areclassfiles, but nojarfile.
- Inspect the
- Build the project, by calling the maven default lifecycle phase that does the same as before, but also produces
a
jarfile.- Inspect the
targetfolder. Verify there areclassfiles, and ajarfile.
- Inspect the
Vulnerability scans
- Every project dependency is a potential liability. Whatever vulnerability is included in one of your dependencies, is potentially also a security risk for your own project.
- Luckily
pom.xmlfiles are an explicit form of declaring dependencies, that is, by inspecting thepom.xmlpotential vulnerabilities are easily detectable. - Searching (and fixing) vulnerable dependencies known as vulnerability scans.
IntelliJs vulnerability plugin
- Intellij has by-default-activated plugin named: Package Checker
- In class, you've seen a short demo of how to use the tool.
- When a
pom.xmlfile is opened, vulnerable dependencies are hihglightes with a different background - Hovering over the highlighted zones shows additional information on the vulnerability cause (and how to fix it)
- When a
Your turn
- Open your XoxFrontend project in IntelliJ.
- Double-click the
pom.xmlfile. - Carefully inspect the background colour of all lines. You'll see some lines highlighted by the Package Checker plugin.
- Hover your mouse over a highlighted line. Wait a second, a popup will appear.
- Double-click the
- Carefully read the message, it will tell you how to fix the vulnerability that you currently have in your project.
- Fix the vulnerability, and make sure your project can still be built.
Sideloading
- Sideloading refers to "outsmarting" maven's dependency resolve algorithm by artificially injecting an artifact
directly into the local
.m2respository. - This technique allows usage of dependencies that do not exist on the official online maven repository, and hence could not be automatically resolved by maven.
- The trick relies on the fact that maven will never search for an artifact online, once it has been found in the local repo.
Example:
XoxFrontendwill be needing functionality from the clonedXoxInternalsproject.- In this case
XoxFrontendcan declare a<dependency>in it'spom.xmlfile: - If we sideload
XoxInternalsinto the local.m2cache, the dependency is directly:- Maven does not need to search on online server for the artifact (we injected it ourselves)
XoxFrontendcan use the library code without code duplication.
- In this case
There are different ways to sideload artifacts into the local .m2 repository cache.
Do not copy code!
Do not copy past code from the cloned XoxInternals project. The goal is to use code from XoxInternals as maven dependency, not by code duplication.
Sideloading from maven projects
- The easiest form of sideloading occurs when the dependency in question is itself a maven project.
- Luckily this is the case.
XoxInternalshas apom.xml, and is itself a maven project. - In this case the
installphase can be used, to not only build an artifact, but also sideload it into the local cache.
Your turn
- Add the above
dependencyblock to theXoxFrontend'spom.xmlfile.- It will show up red. The dependency cannot be resolved, because no such artifact is on the official maven servers.
- Next: Inspect your local
.m2directory. It may be hidden on your system. If it is not visible in the file manager, open a terminal and access the hidden.m2directory on your home folder.- Inspect the content, verify there is no artifact
ca/uqam/info/xoxinternals
- Inspect the content, verify there is no artifact
- Build the previously cloned
XoxInternalsproject using theinstallphase. - Inspect your local
.m2cache again. You should not see a new artifact inca/uqam/info/xoxinternals. - Switch back to the
XoxFrontend'spom.xml, the dependency should now no longer show red, but be correctly resolved.
Next we want to see if we can actually use the code from the correctly resolved dependency:
- Add a new launcher to the XoxFrontend project that uses functionality from the XoxInternals project.
-
Use the below code, to initialize a new game instance between
For the two missing calls, you can use the below helper classes:AliceandBob: -
XoxGameInitiator.java:public class XoxGameInitiator { /** * Creates a new game instance for the given player names. * * @param playerName1 name of first player. * @param playerName2 name of second player. * @return long value of a unique game ID, that can be used to interact with game instance via * manager. */ public static long createNewGame(String playerName1, String playerName2) { Player player1 = new Player(playerName1, "#0000FF"); Player player2 = new Player(playerName2, "#00FF00"); List<Player> playerList = new LinkedList<Player>(); playerList.add(player1); playerList.add(player2); XoxInitSettings xoxSettings = new XoxInitSettings(playerList, playerName1); return XoxManagerImpl.getInstance().addGame(xoxSettings); } } XoxBoardAndActionPrinter.java:public class XoxBoardAndActionPrinter { public static void printBoardAndActionsForPlayer(long gameId, String player) { System.out.println(XoxManagerImpl.getInstance().getBoard(gameId)); // Print all possible actions for Alice XoxClaimFieldAction[] actions = XoxManagerImpl.getInstance().getActions(gameId, player); for (int i = 0; i < actions.length; i++) { System.out.println(actions[i]); } } }
Setup the maven exec plugin in your pom.xml and make sure you can compile and run your XoxFrontend with:
mvn clean compile exec:java
Sideloading from generic JAR files
- Often the library you're missing is itself not provided as source code, but you have only a jar file.
- Possibly the library is not even a maven project !
- It is still possible to sideload just from a jar file, directly into the local
.m2repository cache. - In the last course, you've seen a maven command to do just that.
Your turn
- Build the
XoxInternalsproject withmvn clean package - Copy the
jarfile from thetargetdirectory to your Desktop. - Delete the
XoxInternalsproject from your hard drive, but keep thejarfile. - Delete the
XoxInternalsartifact from your local.m2repository cache.
Clear you local repo!
The above steps are important. From the previous exercise you still have the XoxInternals artifact in your local repo.
At this point the
XoxFrontendproject will no longer work, because we've manually removed theXoxInternalsprojects it depends on.`
- Just using the saved
jarfile, use the mvn command seen in class to directly install an artifact from ajarfile. - Make sure to use the correct
groupId,artifactIdandversion, so the dependency can be correctly resolved. - Verify your local
.m2content and verify that you can now once more build and run theXoxFrontendapplication.
Third party repositories
Third party repositories are online folders providing unofficial maven artifacts. There are several reasons for placing artifacts in third party repos, notably access restriction and the ability to revoke.
Getting a dependency from a third party repo
- Instead of sideloading the
XoxInternalsartifact manually, it is preferrably to retrieve the artifact from a non-official third-party repo. - Reminder, maven's resolving algorithm is:
- First search to local cache for a match (local
.m2directory) - Only as fallback: search the third party repos (if defined)
- Only as last resort: searches the official maven servers.
- Sideloading targets the first step. Third party repos the second step.
In the next exercise you will be using a third party repository, instead of manually sideloading an artifact.
Your turn
- Delete the sideloaded Xox artifact from your local
~/.m2/repository/directory.
Clear you local repo!
The above steps are important. From the previous exercise you still have the XoxInternals artifact in your local repo. If you do not delete it, maven will stop after step 1 and never search for the artifact online.
- Try to compile your
XoxFrontendproject. It will fail, becauseXoxInternalscan no longer be resolved. - Access your
XoxFrontendproject'spom.xmland add a reference theinf2050repo (which is a non-officiel 3rd party maven repo, created specifically for this course): - Compile your project again with:
mvn clean test - Carefully inspect the output.
- Find the output line that indicates the missing artifact has been downloaded from the third party server.
- Verify the build was once more successful.
Why is there suddenly again a copy of XoxInternals in your local cache ?
Maven always caches artifacts locally, once they were successfully retrieved. Otherwise, you would never be able to work offline.
Build profiles
- Build profiles allow you to develop different version of an application, by simply specifying a profile name along the standard maven command.
- The syntax is
-P(for profile), directly followed by the profile name.- Note there is no space between the
-Pswitch and the profile name. - Example: mvn clean package
-Ppremium-software-version
- Note there is no space between the
Alternative launchers
- One use case of build profiles is the specification of alternative launchers.
- This way different functionality of a software can be started, or different hard coded parameters can be used.
Your turn
- Revise the build profile syntax presented in the last course and modify your XoxFrontend to contain two launcher classes:
- For the first launcher, you can reuse the one you coded for Alice and Bob, earlier in this lab session.
- A second launcher, to initialize a game between players
EveandBob.
- Modify the
XoxFrontendproject'spom.xml, so two new build profiles are defined:alice-and-bobas default profile.eve-and-bobas alternative profile.
- For each build profile, add a configuration of the
exec plugin, make sure that:- The
alice-and-bobprofile launches the originalXoxAliceAndBobjava launcher class. - The
eve-and-bobprofile launches the newly createdXoxEveAndBobjava launcher class.
- The
- Build and launch both variants using either of:
mvn clean compile exec:javamvn clean compile exec:java -Palice-and-bobmvn clean compile exec:java -Peve-and-bob
- Verify all commands print an empty board of the initialized game, but only the
alice-and-bob/defaultprofile additionally prints a list of player actions.