Lab 3 - Development Environment
During this lab you will finally work as developers (during previous labs you already have tried managers/system analysts roles). But in order to develop something you must first set up the development infrastructure.
Setting Up Development Environment
JAVA and your favorite IDE should already be quite familiar to you. During the next labs, your chosen IDE becomes your main development tool. You will keep your code in the already well-known Bitbucket repository. The same environment where you published analysis documents produced during the previous labs.
Installation
Downloading and Installing required components:
- JAVA 8.X (SE JDK) - http://www.oracle.com/technetwork/java/javase/downloads/index.html (JAVA_HOME)
- Install your favorite IDE in case you have not already done it
- Eclipse. For labs, it is enough to have just an Eclipse IDE for Java Developers
- Do not forget to properly set the installed JDK as default JRE in Eclipse:
- Go to Window > Preferences > Java > Installed JREs > Add…
- Choose "Standard VM". Next, point the JRE home path to your JDK installation folder (for example, C:\Program Files\Java\jdk1.8.0_51)
- Make your JDK the default environment
- Apply and Close
- Install the Eclipse extensions:
- Eclipse gradle integration
- JavaFX support for eclipse - We recommend installing all components, not only the ones selected in this tutorial
- Scene builder - This is not really an extension, but will be used with Eclipse. Set the path to Scene Builder in the Eclipse preferences window (Window > Preferences > JavaFX)
- Do not forget to properly set the installed JDK as default JRE in Eclipse:
- IntelliJ IDEA. Download it from https://www.jetbrains.com/idea/download
- IntelliJ IDEA should be already configured to work with JAVA 8. However, you can check it in the "Switch IDE Boot JDK" Window (Press Ctrl+Shift+A > Type "Switch IDE Boot JDK" > Enter)
- Gradle and JavaFX support should be already installed in both community and ultimate editions. However, you can check it in the Plugin settings window (File > Settings > Plugins)
- Scene builder - This is not really an extension, but will be used with IntelliJ IDEA. Set the path to Scene Builder in the Settings window (File > Settings > Languagues & Frameworks > JavaFX)
- Eclipse. For labs, it is enough to have just an Eclipse IDE for Java Developers
- Git*
- Download
- For Windows select: Run Git from the Windows Command Prompt
- During installation you are asked how to deal with file endings. Choose "Checkout Windows-style, commit Unix-style line endings".
- On OS X Git is preinstalled
- For Windows select: Run Git from the Windows Command Prompt
- SourceTree - if you like to use a GUI we recommend this classic tool.
- Plugin for your favorite IDE:
- If you are using Eclipse, you may consider using the EGit plugin. It can also be easily installed from the Eclipse Marketplace and may be already included in some Eclipse installations. This is an alternative to using SourceTree.
- If you are using IntelliJ IDEA, it has already the Git integration enabled.
- You can also run git from command line
- Download
- Gradle:
- Download (no installation, only needed for the demo application)
* (if you wish, you are allowed to use other code versioning systems, but if you are not yet proficient with another VCS we encourage the use of Git. Using another VCS may also mean that you will not be able to receive any support regarding it from your supervisor.)
Empty Demo Application
(for your own examination - not for submission)
Before you start developing the current homework application we test everything with a demo application. Demo application demonstrates how to work with gradle and git.
Disclaimer: Commands in the following instruction are given for Windows. On Linux and OS X some commands have to be altered, some alterations are given in brackets.
Gradle
Download gradle if you haven't done it yet. We are now going to create a gradle project. Open command line and type
mkdir test-project
cd test-project
- Now we are in an empty folder
[path to downloaded gradle]\bin\gradle tasks
- What do you see? Which tasks could be useful?
- With
init
we can set up a new gradle project
[path to downloaded gradle]\bin\gradle init
dir
(orls
on Linux/OS X)- Which files were generated?
- Look into build.gradle. Here we can specify how to build the project.
gradlew tasks
(or./gradlew tasks
on Linux/OS X if the first does not work)- What happened?
- We can now run gradle without typing the long path to the original download.
- In the future we add this gradle wrapper (gradlew) to our project repository, which makes it possible for anyone who downloads our project to run gradle.
Now let's create a simple java application. Create the following folder structure "src\main\java\example". Gradle expects to see this folder structure. Project code will be located in "src\main\java". Project resources will be loacated in "src\main\resources". Test code and resources will be located in "src\test\java" and "src\test\resources" respectively.
Create a file named Main.java in the example folder with the following content
package example; public class Main { public static void main(String[] args){ System.out.println("Hello gradle!"); } }
We would like to build this project. gradlew tasks
does not display any tasks to do that. This means that we have to modify the build.gradle file to enable additional tasks.
Delete everything in build.gradle and add this line:
apply plugin: 'java'
Run gradlew tasks
and see which tasks were added. You see that we can now build the project. Run gradlew build
and see if the build succeeds. In gradle we can add a lot of functionality with just adding plugins, since these tasks are needed by a lot of projects.
Now let's add another useful plugin with the line:
apply plugin: 'application'
Running gradlew tasks
now shows that we can run the project. Try it out with gradlew run
. It should throw an exception stating that we haven't specified the main class, which makes sense.
Add the following line:
mainClassName = 'example.Main'
Now run the project again. Did it work?
Until now we have done everything on the command line. But don't worry, using gradle does not mean that we have to do that. First, make sure that you have installed or enabled the Gradle features in your favorite IDE (please check the installation instructions given above). Then, open your Gradle project:
- If you are using Eclipse, choose "Import" > "Gradle" > "Gradle project" and import the project to Eclipse. Now choose "Window" > "Show view" > "Other" > "Gradle tasks". In this view, choose your project. Now you can run the Gradle tasks from within Eclipse.
- If you are using IntelliJ IDEA, just go to "File" > "Open…" and select the project folder on your file system. Then, go to "View" > "Tool Windows" > "Gradle" to open the Gradle view. Here, you can run the Gradle tasks from within IntelliJ IDEA.
How is all this useful? We could also create a project in our favorite IDE and run it there. One advantage of Gradle is that it makes dependancy management easier. Namely, you can just specify the needed dependencies in build.gradle and Gradle will download them for you. Another advantage is that if someone else wants to run your project, they need to have neither the same IDE nor the same operating system. Let's try this out and commit our project to Bitbucket.
Git
Create a new project on bitbucket. After creating the project, bitbucket gives you instructions on what to do next. Open command line, move to the project and type
git init
- Now we created a new local git repository
git remote add origin [bitbucket link to repo]
- Now we added a link to the remote repository
Our local project repository is linked to the remote repository on bitbucket.
Now we would like to add files to the repository, but it makes sense to not add all files. If you type git status
on the command line, you can see which files git sees as new. For example device and user specific files should not be added. For this let's create a file named ".gitignore" to specify files that git should ignore. Add following to ".gitignore":
.classpath .gradle .idea .project .settings bin/* build/*
You see that we ignore build files and IDE specific files. When you run git status
again you see that the list of files is reduced.
Now we can add all remaining files and commit them by running
git add .
git commit -m "our inital commit"
git push -u origin master
(next time we can push by justgit push
)
Go to your bitbucket page and see if changes appeared online.
Now how can others get the code? Go to the bitbucket project page with another computer. Copy the git link and run on command line
git clone [path to bitbucket repo]
- This downloads the code from the remote repository
cd [project-name]
gradlew run
(under Linux/OS X you may have to runchmod +x gradlew
first to set correct permissions)
What happened? Was gradle downloaded? Did the project run? Now you can import the project to your IDE.
When you add changes and want to get them to the repository you have to run
git add .
git commit -m "commit message"
git push
To get new code:
git pull
Bitbucket issue tracker
Go back to the Bitbucket project page. Add issue tracker to your bitbucket project (Settings -> Issue Tracker Settings). Then go to Issues and add a first task for example with the title “Make program say hello to Bitbucket instead of Gradle”. Since this is the first task added, it will get “1” as its issue number.
We will now resolve this task. For this
- Make changes to Main.java, so that the output is "Hello Bitbucket" instead of "Hello Gradle".
- Notify git that changes were made to this file
git add .
- Commit changes and close the issue
git commit -m "Hello message changed, close #1"
- Push changes to the remote repo
git push
Go to the Commits page and see if you can see the first commit, see if “#1” links to the task we created under issues and if the issue is now closed.
There was some magic here:
- When we include an issue number in the commit message we can do several things, for example:
- Refer to an issue with “see #<issue number>”
- Close an issue with “close #<issue number>”
- See here for more options
- Bitbucket saw that we wanted to close issue #1, so it closed the issue
- Bitbucket also created a link in the commit message so that we can find the issue easily
Git merge conflicts
Now we will see what happens if there are conflicts. Clone the project either onto a second computer or into another folder so that there are two copies of the project. Let us call them ProjectA and ProjectB.
Under ProjectA make changes to the main method in Main.java, for example make the program output something in addition to "Hello gradle!". Now commit the changes and push the commit to the remote repository (Reminder: git commit -m "commit message"
and git push
).
Now under ProjectB make some other changes to Main.java. Notice that since you haven't pulled code from the remote repository you will modify the original Main.java file. Commit the changes.
Now when you try to push them git will say that
! [rejected] master -> master (fetch first) error: failed to push some refs to 'path/to/your/repository'
This means that since the last time you updated your local repository someone else has changed the code.
You now have to update your local repository by calling:
git pull
Git will now say that it cannot merge local and remote changes:
78db747..88b85d6 master -> origin/master Auto-merging Main.java CONFLICT (content): Merge conflict in Main.java Automatic merge failed; fix conflicts and then commit the result.
This means that you have to resolve the merge conflict by yourself. Open the Main.java file. You should see something similar to:
package example; public class Main { public static void main(String[] args){ System.out.println("Hello gradle!"); <<<<<<< HEAD System.out.println("This was added by ProjectB"); ======= System.out.println("This was added by ProjectA"); >>>>>>> 7d4797dc57979e5dbe84cbe5f6b0ec2b280fca89 } }
Code between
<<<<<<< HEAD
and
=======
is code that was added by you.
Code between
=======
and
>>>>>>> 7d4797dc57979e5dbe84cbe5f6b0ec2b280fca89
was added by someone else.
You can solve the merge conflict by removing these markers and changing the code so that it encompasses both changes correctly. Then call
git add src\main\java\example\Main.java
(or git add .
)
Now commit and push changes made for the merge.
Go to Bitbucket. If you go to the Commits page of your project you should see a graphical representation of this merge.
If you wish to look into some additional introductions, then a good introduction to git is given here. You can also run git from a GUI application or from within your favorite IDE.
Your Task (must be submitted)
In the demo task you saw how to set up a new java gradle project. In your homework you will modify an existing application. During the first lab you forked the course project. Now it is time to clone your forked project with git and modify some code.
The application is a point-of-sale application that is not quite finished. Your task during labs 3, 4 and 5 is to finish this application. In this and the following homeworks you should keep your issue tracker up to date. All commits should be linked to tasks in the issue tracker and all finished tasks should be closed.
For this homework you have to
- resolve a merge conflict with git (see git task)
- add a new tab introducing your team (UI should be written in fxml file)
- customise the look of the application
Introduction
Gradle
Import the project into your favorite IDE as a gradle project. First thing you will notice, is that the IDE will create 3 separate projects. We are using a multi-project layout. We have one application that can run in two different ways, as a GUI application and as a command line application. The root project contains code that is used by both sub-projects. The two sub-projects contain the GUI and command line specific code. This means that we have three different build.gradle files. Look how the build.gradle files of the sub-projects specify different main classes. Try out which tasks are specified for the root, GUI and command line projects.
You can run the graphical user interface with:
gradlew :SaleSystemGUI:run
and the command line interface with:
gradlew :SaleSystemCLI:run
In the commands of the form gradlew :A:b
the first ":" stands for root, "A" is the selected project and b the selected task.
Javafx
You are already familiar with javafx from the course Object-Oriented Programming. Until now, you have probably created UI objects in code. Javafx makes it possible to separate UI completely from other code. If you look into SalesSystemGUI/src/main/resources/ee/ut/math/tvt/salesystem/ui you see two .fxml files. This is where the user interface files are defined. The file is in FXML format, which is a special kind of XML. It is not the easiest format to edit. Luckily there is another option.
You are provided with 2 different ways to edit the .fxml file:
Scene Builder
The other option is using Scene builder. Right click on the .fxml file and choose "Open with" --> "Other" --> "Scene Builder" (under external programs). Scene builder opens the .fxml file and displays the corresponding UI. Now you can drag around elements as well as drag and drop new elements. If you click save, the changes are applied to the .fxml file.
One disadvantage of Scene Builder is that the generated FXML is not very clean. This can of course be manually fixed in the .fxml file.
Task 1: Git task (2p)
For this task you should create a merge conflict. You should also keep track of the task by creating a Bitbucket issue and linking it to the commits.
Creating a merge conflict means that two members of your team will make changes to the same file at the same time. Both students commit their changes. First student will be able to push his changes to the remote repository. Second student will have to pull these changes and merge them with his own changes.
This task should be simple if you have completed the demo tasks above.
Choose a file that you will use for this task. The merge conflict should contain at least the following:
- changes by both students on an existing line of code
- adding a line of code by both students at the same place in file
- changing a line that is only changed by one student
E.g. for a file that contain the following 4 lines:
This is an example file
Student 1 could commit these changes
This is changes an interesting example file
And student 2 could commit
This is another change an simple example file green
Your task: Create a task under issues in Bitbucket. Link all commits to this task and close the task with the commit where you merge the code. And of course: solve the merge conflict.
Task 2: Team tab (5p)
The team tab should present the following information
- Team name
- Team contact person
- Team members
- Team logo (random image)
You should create a file called application.properties that will hold team information. All information displayed in the introduction tab should be read from the application.properties file. For the team logo the path to the image should be read from application.properties (the image may (but does not have to) be located on the internet). This file should be stored in the resources folder. Make sure that you created UI object of this tab using .fxml file. The application.properties file should be located in the main project. It should also be possible to ask for team information (excluding the image) from the CLI application.
Task 3: Customising the look (2p)
Look into DefaultTheme.css (located in src/main/resources/ee/ut/math/tvt/salesystem/ui). The look of the application is defined here. The look of the application can be defined in a css file. To use this css file add the following line to the start
method in SalesSystemUI
.
scene.getStylesheets().add(getClass().getResource("DefaultTheme.css").toExternalForm());
Run the application. You will see that most of the application has a different look now. Look through the application and check if everything is consistently coloured. If not, make appropriate changes. (Tip: you will probably have to change the newly added TeamTab.fxml. Look through other fxml files and try to figure out which properties define the look of the tab)
Submission of results (1p)
Your results must be submitted using your Bitbucket repository. You should keep track of your tasks using the Bitbucket issue tracker. Every commit should be linked to a task by using “see #<issue number>” and “close #<issue number>” in the commit messages. When all tasks regarding this homework are done, create a tag named "homework-3" and add a link to the readme file in your repository, this will count as a submission (1p). You can create a tag by typing git tag -a homework-3
and then pushing the tag by git push --tags
.
NOTE: In the assessment/consultation lab you must be able to show partial solutions of all tasks.