TDDE51 Methods and tools for large distributed projects (6 ECTS)
Vt1-Vt2 2024
# Build tools - Lab 2
Using a tool to facilitate the build process of software is very useful.
One of the most popular tools for this is the Maven.
With the Maven you can make the build process much easier, keep track of dependencies, guarantee that everyone builds the product in the same way, run tests and generate documentation.
In the laboration you should see how to use the Maven by building a project.
Maven is created with Java in mind, but as with most other building tools, other languages can also be constructed.
Much of what the Maven makes is about executing plugins and through these, one can also integrate several languages in the construction process.
## Documentation
- Good overview of Maven: [http://tutorials.jenkov.com/maven/maven-tutorial.html](http://tutorials.jenkov.com/maven/maven-tutorial.html)
- Build LifeCycle: [https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html](https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html)
- Develop plugins: [https://maven.apache.org/guides/plugin/guide-java-plugin-development.html](https://maven.apache.org/guides/plugin/guide-java-plugin-development.html)
- Manage multiple modules: [https://books.sonatype.com/mvnex-book/reference/multimodule.html](https://books.sonatype.com/mvnex-book/reference/multimodule.html)
- Profiles (for higher grades): [http://maven.apache.org/guides/introduction/introduction-to-profiles.html](http://maven.apache.org/guides/introduction/introduction-to-profiles.html)
## Task
You should use Maven to build a system, manage dependencies, develop a plug-in and configure the system for different environments.
If you already have an existing project, you are free to use it, as long as it can be used to achieve the laboratory requirements.
If you do not have a suitable project, you can use you that code that we give you, a Java client and a go server.
You will find go server here: git@gitlab.liu.se:large-scale-dev/ci-sample-project.git.
The code for the Java project is given further down, but you will create the folder structure themselves.
How to build the GO code can be seen in the project's readme.md.
To build something in the Maven, it is easiest to use a plugin.
One who works well to use is: [https://github.com/raydac/mvn-golang](https://github.com/raydac/mvn-golang).
You can also accomplish this by executing Shell scripts from the Maven, or developing your own plugin.
### Requirements
For this project, you will now write a maven configuration that meets the following requirements:
- The main project that you will structure must have at least two modules.
If you use your own code, you will structure this as you want, it should be any communication between the modules.
If you use the code that we provide, the server and client must be two separate modules.
The main project should be parent of the two modules.
- By running `mvn Package`, the system should build and pack the code.
For Java code, this must mean that e.g.Create a JAR file.
For other languages, you themselves decide what is best, for Go, for example, you can create a binary.
- If you run `mvn test`, the unit test for all modules will be run.
- All dependencies should be handled in the POM files.
By using the Maven to handle dependencies, you do not have to make sure to always have the correct version downloaded.
- Much of Maven revolves around plugins, so now you will developing a plugin of your of own to see how this works.
Your plugin should be used in the Compile phase.
- Your plugin only needs to consist of a mojo.
- It should receive a file name as parameter.
- You should perform any operation using this file. For example load it, execute it or write to it.
### For higher grade
For higher grades, profiles should also be used.
There should be at least two profiles, what these should be used to be up to you.
The requirements are as follows:
- Depending on the profile selected, any line in a file should be changed.
- The Pom.xml file should use a variable that is put on the choice of profile.
For the Go server and Java client is the following suitable:
2 different profiles;A test profile and an Development profile.
The test profile, the logs must be written to the `Logs/Test.Log` folder and in the Dev profile ` Logs/Dev.log`.
To achive this, you will need to change in Log4J.Properties, see more information below.
### Reporting
The task is reported by recording a screencast where you explain the various aspects of your assembled CI system and show how it works as a whole.
Demonstrate how you have structured the project, and each part of your POM.
Be sure to explain what is happening in every step.
### Code
Note that timeretrievers and timeretriever test have dependencies that must be handled.
_HelloMaven.java_:
package se.liu.ida.hello;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
public class HelloMaven {
public static void main(String[] args) {
try {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet getRequest = new HttpGet( "http://localhost:8080/list");
getRequest.addHeader("accept", "application/json");
HttpResponse response = httpClient.execute(getRequest);
if (response.getStatusLine().getStatusCode() != 200) {
throw new RuntimeException("Failed: status code 200 != " + response.getStatusLine().getStatusCode());
}
BufferedReader br = new BufferedReader(
new InputStreamReader((response.getEntity().getContent())));
String output;
System.out.println("Output from Server .... \n");
while ((output = br.readLine()) != null) {
System.out.println(output);
}
httpClient.getConnectionManager().shutdown();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
_TimeRetriever.java_:
package se.liu.ida.hello;
import org.joda.time.LocalTime;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class TimeRetriever {
public static String getTimeMessage() {
Logger logger = LogManager.getLogger(HelloMaven.class);
LocalTime localTime = new LocalTime();
logger.info("Requested time string: " + localTime.toString());
return "TODO list: " + localTime.toString();
}
}
_TimeRetrieverTest.java_:
package se.liu.ida.hello;
import static org.junit.Assert.*;
import junit.framework.TestCase;
import org.joda.time.LocalTime;
public class TimeRetrieverTest extends TestCase {
public TimeRetrieverTest(String name) {
super(name);
}
public void testTimeRetriever() throws Exception {
LocalTime before = new LocalTime();
String testString = "TODO list: " + before.toString();
String actualString = TimeRetriever.getTimeMessage();
assertTrue(testString.compareTo(actualString) <= 0);
}
}
_StatusIT.java_:
package se.liu.ida.hello;
import static org.junit.Assert.*;
import junit.framework.TestCase;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.HttpResponse;
public class StatusIT extends TestCase {
private static String serverURL = "http://localhost:8080/list";
public StatusIT(String name) {
super(name);
}
public void testStatusCode() throws Exception {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet getRequest = new HttpGet(serverURL);
getRequest.addHeader("accept", "application/json");
HttpResponse response = httpClient.execute(getRequest);
assertTrue(response.getStatusLine().getStatusCode() == 200);
}
}
The Main function is in the class _HelloMaven_.
It uses the _TimeRetriever.java_
_TimeRetrieverTest.java_ tests the TimeRetriever class.
_StatusIT.java_ runs a integrations test against servern (integration test is optional).
### Resources
The configuration file for log4j can be seen below.
The row `log4j.appender.R.File=logs/dev.log` will need to change in order when using profiles (higher grade)
_log4j.properties_:
log4j.rootLogger=DEBUG, R
log4j.appender.R=org.apache.log4j.FileAppender
log4j.appender.R.File=logs/dev.log
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
Page responsible: August Ernstsson
Last updated: 2022-01-27