• Appendix
    • ➟ Examination bonus point projects
Collaborative efforts

Is this your TEAM?

Toll

Ein

Anderer

Machts

  1. You are expected to work as a team of three partners.

  2. Using the MI Gitlab SCM is a plus with respect to project evaluation. See table below.

  3. Your team is expected to supply a Maven project based on the MI Maven archetype quickstart available from https://maven.mi.hdm-stuttgart.de/nexus/repository/mi-maven/archetype-catalog.xml.

  4. You are expected to provide good internal code documentation with respect both to method signatures (Javadoc) and method implementation.

You are expected to provide good internal code documentation with respect both to method signatures (Javadoc) and method implementation. Possible problems involve:

Internal code documentation
Compile time warnings

Activate most compiler warnings at EditorInspections. This will show potential compile time problems like dead / unnecessary / unreachable code, unused variable values, shadowing conflicts and so on.

Your method's formal parameters, their type and a method's return type must match your documentation.

 mismatches

You are expected to provide meaningful unit tests:

  • Try to cover all your implementation code and not just isolated modules / methods.

  • If methods allow for null values write suitable tests.

  • Test special cases: If a method expects i.e. an array of strings it may be allowed having zero length.

Your resulting project should be easily installable and runnable.

  • Maven is a good starting point with respect both to testing and cross platform (Unix / Windows / Apple) portability.

  • Avoid dependencies to local file system resources like c:\users\xyz\testdata.txt.

Tip

Test your application's deployability by installing it on an untouched target platform (possibly of a different hard/software architecture) and execute mvn test (provided you do have written meaningful unit tests).

Criterion Percentage
Overall code quality 20%
Code documentation 20%
Unit tests 10%
Deployment 10%
SCM usage 10%
Software functionality 30%
  • Appendix
    • ➟ Examination bonus point projects
      • ➟ Weather forecast
goik@goiki target> java -jar weather-1.0.jar Stuttgart 
1 = Stadtkreis Stuttgart         
2 = Regierungsbezirk Stuttgart 
3 = Stuttgart
4 = Stuttgart Feuerbach
5 = Stuttgart Muehlhausen

Bitte gültige Auswahl 1 bis 5 treffen:2 
Vorhersage für Regierungsbezirk Stuttgart 
Dienstag, 15.05
    23:00:  11°C, Leichter Regen
Mittwoch, 16.05
    02:00:  10°C, Leichter Regen
    05:00:  10°C, Leichter Regen
    08:00:  11°C, Leichter Regen
 ...
https://api.openweathermap.org/data/2.5/forecast?lang=de& 
APPID=7cufdhdcgdhsgdhgfcgsdss67b3&units=metric&id=3214105


{"cod":"200","message":0.0042,"cnt":40,"list":[            
 {"dt":1526428800,"main":{"temp":10.29,"temp_min":10.29,
"temp_max":12.45,"pressure":985.75,"sea_level":1027.48,
"grnd_level":985.75,"humidity":80,"temp_kf":-2.16},
"weather":[{"id":500,"main":"Rain",
"description":"Leichter Regen","icon":"10n"}],"clouds":
{"all":88},"wind":{"speed":1.59,"deg":313.503},"rain":
{"3h":0.315},"sys":{"pod":"n"},"dt_txt":"2018-05-16 00:00:00"},           
{"dt":1526439600,"main": ...

An URL containing an id value corresponding to a uniquely defined town or region. We identify the following components:

lang=de

Provide German localization e.g. «Leichter Regen» in favour of «light rain».

APPID=7cufdhdcgdhsgdhgfcgsdss67b3

This parameter allows for accessing the service: «7cufdhdcgdhsgdhgfcgsdss67b3» is actually a fake value. Your project requires obtaining an APPID token.

units=metric

Favour metric over imperial units.

id=3214105

«3214105» identifies «Regierungsbezirk Stuttgart», see line 262703 in cities.list.json:

"id": 3214105,
"name": "Regierungsbezirk Stuttgart",
"country": "DE",
"coord": {
  "lon": 9.66667,
  "lat": 49.083328
}

https://openweathermap.org/api's reply providing JSON based weather data.

[
  {
    "id": 2886241,
    "name": "Regierungsbezirk Köln",
    "country": "DE",
    "coord": {
      "lon": 7.16667,
      "lat": 50.833328
    }
  },
  {
    "id": 3247452,
    "name": "Kreis Euskirchen",
...
]
FileUtils.copyURLToFile(
  "https://api.openweathermap.org/data/2.5/forecast...",
  new File("weatherData.json"));
<dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
  <version>2.6</version>
</dependency>
public class Cities {
  static public final City[] cities;
   ...
}
@Test public void testParsedCityCount() {
  Assertions.assertEquals(209579, Cities.cities.length);
}
public class WeatherDataParser {

  static public final Weather parse(final String jsonWeatherDataFilename)
     throws IOException {
    return ...;
  }
}
@Test public void testParseWeatherData() {
...
  Weather weather = WeatherDataParser.parse(
    "src/main/resources/stuttgart.weather.json");
...
  1. The application shall accept a command line parameter like e.g. «Stuttgart» to filter matching cities from cities.list.json.

  2. If a given filter matches multiple locations the user shall have an option for choosing the desired one.

  3. The most recent city id value shall be cached in a file. Subsequent invocations without command line parameter shall provide a current forecast corresponding to this value.

  4. Weather data belonging to a given id value shall be cached locally for 10 minutes. Subsequent weather queries within this period shall be read from cache rather than by accessing https://api.openweathermap.org/... .

    Provide logging to a file rather than to the console to avoid cluttering the user interface. Log cache handling.

  • Provide logging to a file rather than to the console to avoid cluttering the user interface.

  • Log cache handling.

main INFO  weather.Forecast - Re-using cache file
 '/ma/goik/Forecast/6930414.json' from 196 seconds ago
  • Appendix
    • ➟ Examination bonus point projects
      • ➟ Reverse Polish notation (RPN) calculator
        • ➟ Implementation hints
final String[] patterns = new String[] {
  "sqrt",
  "[-]?([0-9]+[.]?[0-9]*|[.][0-9]+)(E[-]?[0-9]+)?",// Matches e.g. -1.5E-33
  "\\+"};// Escape required avoiding regular expression syntax clash.
final String expression = "2.1 -3.4 sqrt";
try (final Scanner scanner = new Scanner(expression)) {
  while (scanner.hasNext()) {
    for (final String p: patterns) {
      if (scanner.hasNext(p)) {
        IO.println("Token '" + scanner.next(p) +
            "' matched by '" + p + "'");
        break;
      }
    }
  }
}
Token '2.1' matched by '[-]?([0-9]+[.]?[0-9]*|[.][0-9]+)(E[-]?[0-9]+)?'
Token '-3.4' matched by '[-]?([0-9]+[.]?[0-9]*|[.][0-9]+)(E[-]?[0-9]+)?'
Token 'sqrt' matched by 'sqrt'
...
final String[] patterns = new String[] {
  "sqrt",
  "[-]?([0-9]+[.]?[0-9]*|[.][0-9]+)(E[-]?[0-9]+)?",// Matches e.g. -1.5E-33
  "\\+"};// Escape required avoiding regular expression syntax clash.
try (final Scanner scanner = new Scanner("2.1 -3.4 pbck") ❶) {
  while (scanner.hasNext()) {
    boolean foundToken = false;
    for (final String p: patterns) {
      if (scanner.hasNext(p)) {
        foundToken = true;
        IO.println("Token '" + scanner.next(p) +
          "' matched by '" + p + "'");
        break;
      }
    }
    if (!foundToken) {
      IO.println("Parsing error at '" + scanner.nextLine() + "'");
      System.exit(1);
    } ...
Token '2.1' matched by '[-]?([0-9]+[.]?[0-9]*|[.][0-9]+)(E[-]?[0-9]+)?'
Token '-3.4' matched by '[-]?([0-9]+[.]?[0-9]*|[.][0-9]+)(E[-]?[0-9]+)?'
Parsing error at 'pbck'
  • Appendix
    • ➟ Examination bonus point projects
      • ➟ Currency converter, Summer 2017
  • Appendix
    • ➟ Exercising past examinations
Image layer 1
Image layer 2
Image layer 3

The following installations allow for exercises with respect to the final examination:

  • E-Exam 113105 Softwareentwicklung 1 Test / Network blocked:

    The examination environment with firewall rules restricting Internet access to a small number of allowed sites.

  • E-Exam 113105 Softwareentwicklung 1 Test / Teamviewer:

    No Internet blocking. Teamviewer allows for getting external help.

  • Appendix
    • ➟ Exercising past examinations
      • ➟ Starting an exam
Image layer 1
Image layer 2
Image layer 3
Image layer 4
Image layer 5
Image layer 6
Image layer 7
Image layer 8
Image layer 9
Image layer 10
Image layer 11
Image layer 12
Image layer 13
  • Appendix
    • ➟ Exercising past examinations
      • ➟ Implementing the project skeleton
  • HTML is difficult to read:

       *     <td><code>a = -3</code>, <code>b = 4</code>, <code>c = 3</code></td>
       *     <td>4 - (-3) = 7</td>
       *   </tr>
       * </table>
       ...
       */
      static public int getMaxAbsoluteDiff(int a, int b, int c) {
        return 42;  // TODO: Implement me correctly
  • ⇒ Generate Javadoc by CLI or Idea.

Image layer 1
Image layer 2
Image layer 3
Image layer 4
Image layer 5
Image layer 6
Image layer 7
Image layer 8
Image layer 9
Image layer 10
Image layer 11
  • Appendix
    • ➟ Exercising past examinations
      • ➟ Finish the exam
Image layer 1
Image layer 2
Image layer 3
Image layer 4
Image layer 5
Image layer 6
Image layer 7
Image layer 8
Image layer 9
Image layer 10
Image layer 11
Image layer 12
Image layer 13
Image layer 14
  • Appendix
    • ➟ Examination hints
  • Zip archive of 10 MB max.

    Caution: Use standard formats e.g. png, gif, pdf. Stuff like .doc, .docx, .rtf may be unsupported

  • Upload your cheat sheet here

    Caution: Unavailable during active e-examinations!

  • Verify your uploaded cheat sheet here.

    Caution: Limited to HdM network / VPN

  • Task definitions by Javadoc.

  • Corresponding Unit tests.

  • Automated evaluation scoring your achievements.

  • Individual weights reflecting a test's significance.

/**
* Finde das n-te ungerade Element einer Wertefolge.
* 
* <p>Beispiel: Im Array {3, 2, 0, 1, 4} ist der Wert «1» an der Index-
*   position «3» das zweite ungerade Element.</p>
* 
* @param werte Die zu durchsuchenden Werte.
* @param n Die gewünschte Position, Start bei 1.
* 
* @return Den Index des n-ten ungeraden Wertes falls es mindestens n
* ungerade Werte gibt, ...
*/
static public int getNtesUngeradesElement(final int[] werte, final int n){     
    return 12345; // TODO: Implementiere mich korrekt!
}
@Test
@Points(2) /* 2 points if test passes */
public void test_400() {
  Assertions.assertEquals(
    2, /* Expected result */
    Helper.getNtesUngeradesElement(new int[]{-4,  6,  1, -2,   8}, 1));
}
Unit Tests Your solution
assertFalse(isPrime(1));
assertTrue (isPrime(2));
assertTrue (isPrime(3));
assertFalse(isPrime(4));
assertTrue (isPrime(5));
assertFalse(isPrime(6));
assertTrue (isPrime(7));
assertFalse(isPrime(8));
assertFalse(isPrime(9));
assertFalse(isPrime(10));
... boolean isPrime(final int p) {
  switch (p) {
    case 2:
    case 3:
    case 5:
    case 7:
      return true;
    default:
      return false;    }

Will be treated as an attempt at deception / Täuschungsversuch.

  • Unit testing is relentless: You are no longer at high school where a result having just a wrong sign used to matter next to nothing.

  • Focus on completing units of work rather than nearly finishing a large number of tasks.

  • Watching a test fail just happens. Learn to systematically fix bugs:

    1. Use your IDE's debugger. Practise debugging Junit tests individually addressing failures one by one.

    2. Insert log statements using log4j.

  1. Task
  2. An IDE warning
  3. Weird output.
  4. Task
  5. Different outputs
  6. Computing the average
  7. Task
  8. Swapping two variables
  9. 0 and null
  10. Task
  11. Executing main(...)
  12. Strange arithmetics
  13. Task
  14. Beginner's nightmare
  15. Strange endless loop result
  16. Task
  17. switch versus if ... else if ... else
  18. Exception handling
  19. Task
  20. Extraterrestrial integer value representation
  21. An initialization issue
  22. Tasks
  23. equals() and hashCode()
  24. The average of three byte values
  25. Tasks
  26. Spoiled execution
  27. Method overriding
  28. Tasks
  29. Type conflict
  30. Weird subtraction
  31. Tasks
  32. Surprising difference
  33. Type assignment problem
  34. Tasks
  35. Return type
  36. Weird behaviour
  37. Tasks
  38. Unexpected value
  39. Assignment problems
  40. NullPointerException problem
  41. Tasks
  42. Logical expression
  43. Device states
  44. Missing exception warning
  45. Task
  46. Wahr oder falsch?
  47. Zeitangaben und hashCode()
  48. Vergleichen von StringBuffer Instanzen
  49. Task
  50. Primitive und Klassentypen
  51. Ein Interface Problem
  52. Mapping color representations
  53. Implementing tasks
  54. equals(...) und hashCode()
  55. Wundersames Ergebnis
  56. Compile time Fehler
  57. Task
  58. Grundrechnen für Anfänger
  59. String Objekte
  60. Garbage collection
  61. Task
  62. Access Modifier
  63. Heap memory cleanup
  64. Task
  65. Klassen und Vererbung
  66. Task
  67. Tasks
  68. Task
  69. Tasks
  70. Compile time error
  71. Tasks
  72. Tasks
  • Appendix
    • ➟ Working with git
  1. Creating an empty new project itself.

  2. Adding fellow project users for participation.

Image layer 1
Image layer 2
Image layer 3
Image layer 4
Image layer 5
Image layer 6
Image layer 7
Image layer 8
Image layer 9
Image layer 10
>git clone git@gitlab.mi.hdm-stuttgart.de:goik/vcintro.git
Cloning into 'vcintro'...
warning: You appear to have cloned an empty repository.
>cd vcintro/
>vim Readme.md
>git add Readme.md
# Initial project description.

Will be extended when adding more assets.
EDITOR=vim git commit Readme.md 
Adding Readme file in Markdown format
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch master
#
# Initial commit
#
# Changes to be committed:
#       new file:   Readme.md
>git push
Counting objects: 3, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 306 bytes | 306.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To gitlab.mi.hdm-stuttgart.de:goik/vcintro.git
 * [new branch]      master -> master
>mvn --batch-mode -e archetype:generate -Dversion=0.9 \
> -DgroupId=de.hdm_stuttgart.mi.sd1 \
> -DartifactId=first -DarchetypeGroupId=de.hdm_stuttgart.mi \
> -DarchetypeArtifactId=mi-maven-archetype-quickstart -DarchetypeVersion=1.2.1
>find first/ -type f
first/.gitignore
first/src/test/java/de/hdm_stuttgart/mi/sd1/AppTest.java
first/src/main/java/de/hdm_stuttgart/mi/sd1/App.java
first/src/main/resources/log4j2.xml
first/pom.xml
> git status
On branch master
Your branch is up to date with 'origin/master'.

Untracked files:
  (use "git add <file>..." to include in what will be committed)

	first/

nothing added to commit but untracked files present (use "git add" to track)
>git add `find first/ -type f`
>git status
On branch master
Your branch is up to date with 'origin/master'.

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	new file:   first/.gitignore
	new file:   first/pom.xml
	new file:   first/src/main/java/de/hdm_stuttgart/mi/sd1/App.java
	new file:   first/src/main/resources/log4j2.xml
	new file:   first/src/test/java/de/hdm_stuttgart/mi/sd1/AppTest.java
>git status
On branch master
Your branch is up to date with 'origin/master'.

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	new file:   first/.gitignore
	new file:   first/pom.xml
	new file:   first/src/main/java/de/hdm_stuttgart/mi/sd1/App.java
	new file:   first/src/main/resources/log4j2.xml
	new file:   first/src/test/java/de/hdm_stuttgart/mi/sd1/AppTest.java
EDITOR=vim git commit -a
Adding a Maven project.
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch master
# Your branch is up to date with 'origin/master'.
#
# Changes to be committed:
#       new file:   first/.gitignore
#       new file:   first/pom.xml
#       new file:   first/src/main/java/de/hdm_stuttgart/mi/sd1/App.java
#       new file:   first/src/main/resources/log4j2.xml
#       new file:   first/src/test/java/de/hdm_stuttgart/mi/sd1/AppTest.java
>git status
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
  (use "git push" to publish your local commits)

nothing to commit, working tree clean
>git push
Counting objects: 22, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (10/10), done.
Writing objects: 100% (22/22), 3.31 KiB | 1.10 MiB/s, done.
Total 22 (delta 0), reused 0 (delta 0)
To gitlab.mi.hdm-stuttgart.de:goik/vcintro.git
   32da2ff..4e19142  master -> master
>git status
...
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   Readme.md
git checkout -- Readme.md
>git status
Your branch is up to date with 'origin/master'.
nothing to commit, working tree clean
>git pull
remote: Enumerating objects: 10, done.
remote: Counting objects: 100% (10/10), done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 6 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (6/6), done.
From gitlab.mi.hdm-stuttgart.de:goik/vcintro
   3751344..83bd7b9  master     -> origin/master
Updating 3751344..83bd7b9
Fast-forward
 Readme.md | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
  • Appendix
    • ➟ Using git

Git:

  1. A completely ignorant, childish person with no manners.

  2. A person who feels justified in their callow behaviour.

  3. A pubescent kid who thinks it's totally cool to act like a moron on the Internet, only because no one can actually reach through the screen and punch their lights out.

  • Appendix
    • ➟ Using git
      • ➟ Working with git locally.

        Creating a git project

        Important commands: git add, git commit, git log, ...

  • git init

  • Result: Sub folder .git containing project's metadata and versioning history

  • public class Math {
    
      static public int add(
       final int a, final int b) {
         return a + b;
      }
    }
  • git status: Math.java yet unversioned.

  • git add Math.java

  • git status: Math.java became versioned.

  • git commit --message "New math class containing single method"

  • Result: Commit change set to repository adding given message to project log.

git status
On branch master 

No commits yet 

Untracked files: 
  (use "git add <file>..." to include in what will be committed)

    Math.java

nothing added to commit but untracked files present (use "git add" to track) 
public class Math {

  static public int add(
   final int a, final int b) {
     return a + b;
  }
}
public class Math {
 /**
  * Summing two int values.
  * @param a first value.
  * @param b second value.
  * @return The sum of both.
  */
  static public int add(
   final int a, final int b) {
     return a + b;
  }
}
git diff tracing changes
>git checkout --  Math.java 

>git diff Math.java 
>

Double dashes '--' disambiguating branch names from file names.

Replace working tree file Math.java by repository master.

No difference working tree to master branch.

> javac Print.java Math.java  # Compilation creating Math.class and Print.class
 
> git status
On branch master
Your branch is up to date with 'origin/master'.

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        Math.class
        Print.class

nothing added to commit but untracked files present (use "git add" to track)
  1. Math.class and Print.class are being generated from Math.java and Print.java.

  2. Rule of thumb: Do not version dependent objects.

Solution: Add a .gitignore file to versioning to contain:

# ignore generated .class files
*.class
git log
commit 0137ccd857a242f4751e36bdbce365c6130c3a32 (HEAD -> master) 
Author: Martin Goik <goik@hdm-stuttgart.de>
Date:   Sat May 25 11:56:00 2019 +0200

    Removing duplicate headline 

commit 7f119fac36e02e4c5a7f04f022217b6f744d6e1d 
Author: Martin Goik <goik@hdm-stuttgart.de>
Date:   Sat May 25 11:49:52 2019 +0200

    Project Readme.md  ...
git checkout 7f119fac36e02e4c5a7f04f022217b6f744d6e1d
Note: checking out '7f119fac36e02e4c5a7f04f022217b6f744d6e1d'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

HEAD is now at 7f119fa Project Readme.md
git checkout master
Previous HEAD position was 7f119fa Project Readme.md
Switched to branch 'master'
  1. git local, DIY
  • Appendix
    • ➟ Using git
      • ➟ Shared development with centralized remote.

        Connecting local to remote repository or clone

        push local to remote

        pull from remote to local

See multi+remote/shared git:

  1. Create empty remote repository on gitlab.mi.hdm-stuttgart.de.

  2. Connect local repository to remote

  3. push or pull content

Step 1: Create remote repository
Step 2: Retrieve remote repository address
git remote add origin  https://gitlab.mi.hdm-stuttgart.de/goik/gitintro.git

origin is an alias for our remote repository https://gitlab.mi.hdm-stuttgart.de/goik/gitintro.git.

git push --set-upstream origin  master
Username for 'https://gitlab.mi.hdm-stuttgart.de': goik 
Password for 'https://goik@gitlab.mi.hdm-stuttgart.de': 
Counting objects: 5, done.
Delta compression using up to 6 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (5/5), 507 bytes | 507.00 KiB/s, done.
Total 5 (delta 0), reused 0 (delta 0)
To https://gitlab.mi.hdm-stuttgart.de/goik/gitintro.git
 * [new branch]      master -> master 
Branch 'master' set up to track remote branch 'master' from 'origin'.
> git pull 
Username for 'https://gitlab.mi.hdm-stuttgart.de': goik 
Password for 'https://goik@gitlab.mi.hdm-stuttgart.de': 
remote: Enumerating objects: 8, done.
remote: Counting objects: 100% (8/8), done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 6 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (6/6), done.
From https://gitlab.mi.hdm-stuttgart.de/goik/gitintro 
   733e541..ffff092  master     -> origin/master
Updating 733e541..ffff092 
Fast-forward
 Math.java | 10 ++++++++-- 
 1 file changed, 8 insertions(+), 2 deletions(-)
  1. Create new possibly non-empty project at https://gitlab.mi.hdm-stuttgart.de.

  2. > git clone https://gitlab.mi.hdm-stuttgart.de/goik/gitintro.git
    Cloning into 'gitintro'...
    Username for 'https://gitlab.mi.hdm-stuttgart.de': goik
    Password for 'https://goik@gitlab.mi.hdm-stuttgart.de': 
    remote: Enumerating objects: 5, done.
    remote: Counting objects: 100% (5/5), done.
    remote: Compressing objects: 100% (4/4), done.
    remote: Total 5 (delta 0), reused 0 (delta 0)
    Unpacking objects: 100% (5/5), done.
    
  • Appendix
    • ➟ Using git
      • ➟ Conflicts

        Line level conflicts

        Manual merge

User A: Print.java User B: Print.java
// Driver class
public class Print {
  static void main() {
      IO.println
        (Math.add(2, 3));
  }
}
/**
 * Application entry point
 */
public class Print {
  static void main() {
      IO.println
        (Math.add(2, 3));
  }
}
User A User B
Edit: ... Driver class ... -
git commit, git push -
- edit: ... Application entry point ...
- git commit
- git push: Fail!
>git push ...
To https://gitlab.mi.hdm-stuttgart.de/goik/gitintro.git
 ! [rejected]        master -> master (fetch first)
error: failed to push some refs to
        'https://gitlab.mi.hdm-stuttgart.de/goik/gitintro.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
>git pull 
...
From https://gitlab.mi.hdm-stuttgart.de/goik/gitintro
   b003a82..dbbedb0  master     -> origin/master
Auto-merging Print.java
CONFLICT (content): Merge conflict in Print.java
Automatic merge failed; fix conflicts and then commit the result.
>git diff Print.java
diff --cc Print.java
index fc36ae6,7b27edf..0000000
--- a/Print.java
+++ b/Print.java
@@@ -1,6 -1,4 +1,10 @@@
++<<<<<<< HEAD
 +/**                        
 + * Application entry point
 + */
++=======
+ // Driver class 
++>>>>>>> dbbedb0fc29d77beeaaada37f2538d78f82bac93
public class Print {
  static void main() {
      IO.println
        (Math.add(2, 3));
  }
}
Struggling for resolution
<<<<<<< HEAD
/**
 * Application entry point 
 */
=======
// Driver class 
>>>>>>> 10cf21c ... 759462c
public class Print {
  static void main() {
      IO.println
        (Math.add(2, 3));
  }
}
/**
 * Driver class, application entry point 
 */
public class Print {
  static void main() {
      IO.println
        (Math.add(2, 3));
  }
}
>git add Print.java 

>git commit --message "Merging changes" 
[master 173487a] Merging changes

>git push
...
To https://gitlab.mi.hdm-stuttgart.de/goik/gitintro.git
   10cf21c..173487a  master -> master
  1. git distributed, DIY
  • Appendix
    • ➟ Apache Maven
  • Build tool

  • Project management tool

    • Create reports

    • Continuous integration support

  • Build tool

  • Dependency management

  • Repository system

  • Plugin framework

  • Sensible default values:

    • Source below ${basedir}/src/main/java

    • Tests below ${basedir}/src/test

    • Bytecode, jar/war archives below ${basedir}/target

    • ...

Image layer 1
Image layer 2
Image layer 3
Image layer 4
Image layer 5
Image layer 6
Image layer 7
Image layer 8
<project xmlns="http://maven.apache.org/POM/4.0.0" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
    http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
...

</project>
  • Declarative project description

    • Dependencies

    • Builds

    • Artifacts

  • No explicit instructions

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-shade-plugin</artifactId>
  <configuration>
    <Main-Class>org.devel.App</Main-Class>
...
      <execution>
        <phase>package</phase>
        <goals>
          <goal>shade</goal>
        </goals>
...
module.o: module.c
	gcc -c -g module.c
  • Appendix
    • ➟ Apache Maven
      • ➟ The project object model pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
              http://maven.apache.org/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>
  <groupId>de.hdm_stuttgart.mi</groupId>
  <artifactId>first</artifactId>
  <version>0.9</version>

</project>
mkdir -p src/main/java 

vim src/main/java/Hello.java 

first> mvn compile ...
[WARNING] File encoding has not been set, using platform encoding UTF-8, 
    i.e. build is platform dependent! ...
[ERROR] error: Source option 5 is no longer supported.  Use 6 or later.
[ERROR] error: Target option 1.5 is no longer supported.  Use 1.6 or later.
>mvn help:effective-pom

<project ...>
   ...
  <plugin>
    <artifactId>maven-compiler-plugin</artifactId> ...

> find ~/.m2/repository/ -name maven-compiler-plugin\* ...
       
>jar -xf ~/.m2/repository/org/apache/maven/plugins/maven-compiler-plugin/3.7.0/maven-compiler-plugin-3.7.0.jar
>cat META-INF/maven/plugin.xml
<encoding implementation="java.lang.String" default-value="${project.build.sourceEncoding}">${encoding}</encoding>
<source implementation="java.lang.String" default-value="1.5">${maven.compiler.source}</source>
<target implementation="java.lang.String" default-value="1.5">${maven.compiler.target}</target>
<project ... xsd/maven-4.0.0.xsd">
...
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties> ...
rm -rf ~/.m2/repository/
mvn compile;     find ~/.m2/repository/ -type f|wc -l
220
Image layer 1
Image layer 2
Image layer 3
Image layer 4
jar -tf /usr/share/apache-maven-3.0.5/lib/maven-model-builder-3.0.5.jar

...
org/apache/maven/model/plugin/ReportingConverter.class
org/apache/maven/model/pom-4.0.0.xml
org/apache/maven/model/profile/activation/FileProfileActivator$1.class
...
...                          <!-- Does this ring a (security related) bell? -->
<repositories>
  <repository>
    <id>central</id>
    <name>Central Repository</name>
    <url>http://repo.maven.apache.org/maven2</url>
...
  <pluginRepositories>
    <pluginRepository>
      <id>central</id>
      <name>Central Repository</name>
      <url>http://repo.maven.apache.org/maven2</url>
...
<settings ... settings-1.0.0.xsd">

  <mirrors>
    <mirror>
      <id>central-secure</id>
      <mirrorOf>central</mirrorOf>
      <name>Maven Central: Favour https over http.</name>
      <url>https://repo.maven.apache.org/maven2</url>
    </mirror>
  </mirrors>
  ...
first> mvn help:effective-pom
... Effective POMs, after inheritance, interpolation, and profiles are applied:

<project xmlns="http://maven.apache.org/POM/4.0.0" ...>
  <modelVersion>4.0.0</modelVersion>
...
      <plugin>
        <artifactId>maven-jar-plugin</artifactId>
        <version>2.3.2</version>
        <executions>
          <execution>
            <id>default-jar</id>
...
  • Appendix
    • ➟ Apache Maven
      • ➟ Plugins
  • Tiny core

  • Plugin extensible

Hint: mvn help:effective-pom lists included plugins.

  • Testing: maven-surefire-plugin

  • Library dependencies: maven-dependency-plugin

  • Packaging: maven-jar-plugin

  • Documentation: maven-javadoc-plugin

first> jar -tf ~/.m2/repository/org/apache/maven/plugins/\
        maven-javadoc-plugin/3.0.0/maven-javadoc-plugin-3.0.0.jar
...
META-INF/LICENSE
META-INF/maven/org.apache.maven.plugins/maven-javadoc-plugin/plugin-help.xml
javadoc-report.properties
META-INF/maven/plugin.xml
log4j.properties
META-INF/NOTICE
org/apache/maven/plugins/javadoc/AbstractFixJavadocMojo$JavaEntityTags.class
org/apache/maven/plugins/javadoc/AggregatorTestJavadocReport.class
...
  • Appendix
    • ➟ Apache Maven
      • ➟ Dependencies
<project ... maven-4.0.0.xsd"> ...
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>...
import org.junit.Test;
import org.junit.Assert;

public class AppTest {
  @Test
  public void doTest() {
    Assert.assertEquals(1, 1);
  }
first> mvn test
[INFO] Scanning for projects...
Running de.hdm_stuttgart.mi.sd1.AppTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.053 sec
first> mvn dependency:tree
        ...
[INFO] de.hdm_stuttgart.mi.sd1:first:jar:0.9
[INFO] \- junit:junit:jar:4.12:test
[INFO]    \- org.hamcrest:hamcrest-core:jar:1.3:test
  • ~/.m2/repository/junit/junit/4.12/junit-4.12.jar

  • ~/.m2/repository/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar

<project ... maven-4.0.0.xsd"> 
      ...
<!-- no such entry -->
  <dependency>
    <groupId>org.hamcrest</groupId>
    <artifactId>hamcrest-core</artifactId>
    <version>1.3</version>
    <scope>test</scope>
  </dependency>
      ...
<dependency>
  <groupId>org.hamcrest</groupId>
  <artifactId>hamcrest-core</artifactId>
  <version>1.3</version>
  </dependency>
</dependencies>
Image layer 1
Image layer 2
Image layer 3
Image layer 4
Image layer 5
Image layer 6
<project ... maven-4.0.0.xsd"> ...
  <dependencies>
    <dependency>
      <groupId>org.testng</groupId>
      <artifactId>testng</artifactId>
      <version>6.14.3</version>
      <scope>test</scope>
    </dependency>...
import org.testng.annotations.Test;
import org.testng.Assert;

public class AppTest {
  @Test
  public void doTest() {
    Assert.assertEquals(1, 1);
  }
testng> mvn test
Running de.hdm_stuttgart.mi.sd1.AppTest
Configuring TestNG with: org.apache.maven.surefire...
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.372 sec
  • Appendix
    • ➟ Apache Maven
      • ➟ Lifecycle, phases and goals
Image layer 1
Image layer 2
Image layer 3
Image layer 4
Image layer 5
Image layer 6
Image layer 7
Phases:

clean, compile, test, package, deploy, ...

Lifecycle

Sequence of named phases

Example: mvn clean (Lifecycle)
  • pre-clean

  • clean (Phase)

  • post-clean

See Default Lifecycle.

<plugin>
  <groupId>com.mysema.maven</groupId>
  <artifactId>apt-maven-plugin</artifactId>
  <version>1.1.3</version>
  <executions>
    <execution>
      <id>process</id>
      <goals>
        <goal>process</goal>
      </goals>
      <phase>generate-sources</phase>
      <configuration>
        <outputDirectory>${project.build.directory}/metamodel</outputDirectory>
        <processor>com.mysema.query.apt.jpa.JPAAnnotationProcessor</processor>
      </configuration>
      ...