Demo application
This tutorial shows how to create a basic java project by using Gradle, Git, and Bitbucket.
- Creating a Gradle project from zero
- Linking the project to Bitbucket using Git
- Using the issue tracker
- Resolving merge conflicts
Disclaimer: The commands in the following instructions are given for Windows. On Linux and OS X some commands have to be altered, some alterations are given in brackets.
Creating a Gradle project from zero
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.
Linking the project to Bitbucket using 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
Using the issue tracker
At this point, you should know how to configure your repository to add a Bitbucket issue tracker or Jira Cloud to manage your user stories and related tasks (if not, check Lab 1). To see how the issue tracker works with the commits, add a new issue report of type task with the title “Make program say hello to Bitbucket instead of Gradle” and remember the task id (for example, #1
if you are using the Bitbucket issue tracker or PROJECTKEY-1
if you are using Jira Cloud).
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 task by referring to to task ID in the commit message
- In Bitbucket issue tracker,
git commit -m "Hello message changed, close #1"
- In Jira Cloud,
git commit -m "Hello message changed, PROJECTKEY-1 #done"
- In Bitbucket issue tracker,
- 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 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>"
(only if you use Bitbucket issue tracker) - Close an issue with
"close #<issue number>"
(only if you use Bitbucket issue tracker) - Transition an issue to a particular status
<transtition_name>
with"<ISSUE_KEY> #<transition_name>"
(only if you use Jira Cloud)
- Refer to an issue with
- Bitbucket saw that we wanted to close the issue, so it closed the issue
- Bitbucket also created a link in the commit message so that we can find the issue easily
For more options:
- See this link for more options on Bitbucket issues
- See smart commits on Jira Cloud.
Resolving 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 favourite IDE.