This handout describes how to perform common Java development tasks in the Allen Center software labs with IntelliJ.

Contents:

Starting IntelliJ

If you are working on your own computer or a CSE Linux Home VM, and you are working through the handouts in the recommended order, you should have installed IntelliJ. Else, it is installed on the department machines.

Starting IntelliJ on Linux

You may be able to click and icon or search for IntelliJ in your program launcher.

Otherwise, go to the directory where IntelliJ is installed and then go into the bin subdirectory. Then type the following command:

./idea.sh

IntelliJ will start up, display a splash screen, and then potentially show a settings import dialog:

Screenshot:
IntelliJ Workspace Selection in Windows

IntelliJ is asking you whether to import settings. If you have used IntelliJ before, pick the first option and locate the settings. Otherwise, pick the second option.

Starting IntelliJ on Windows

From the start menu, search for IntelliJ.

IntelliJ will start up, display a splash screen, and then potentially show a settings import dialog:

Screenshot:
IntelliJ Workspace Selection in Windows

IntelliJ is asking you whether to import settings. If you have used IntelliJ before, pick the first option and locate the settings. Otherwise, pick the second option.

IntelliJ generics errors configuration

We expect your code to not have any generics-related problems. For example, the following code is unacceptable:

List myList = new ArrayList();
myList.add("foo");

The generic type List of myList should be parametrized, for instance, to String by replacing the first line with List<String> myList = new ArrayList<String>(); Note that List<String> myList = new ArrayList(); is also incorrect.

By default, IntelliJ does not show generics problems as or errors. You can run a generify tool to ensure that your code contains acceptable generics.

To make this configuration, go to Refactor » Generify..., update the preferences as required and click on Preview. Use this to ensure that all the changes being made are correct, and click Do Refactor.

Importing Your Project From GitLab

Cloning the Repository

First, set up an ssh key.

Then follow the following steps:

  1. From the main menu, choose VCS | Checkout from Version Control | Git, or, if no project is currently opened, choose Checkout from Version Control | Git on the Welcome screen.
  2. In the Clone Repository dialog, specify the URL of the remote repository you want to clone (you can click Test to make sure that connection to the remote can be established). This should be git@gitlab.cs.washington.edu:cse331-19wi-students/cse331-19wi-YourCSENetID.git (where YourCSENetID is your CSE Net ID)
  3. In the Directory field, specify the path where the folder for your local Git repository will be created into which the remote repository will be cloned.
  4. Click Clone. If you want to create a IntelliJ IDEA project based on the sources you have cloned, click Yes in the confirmation dialog.
Screenshot: Clone Repository

Ensure Project Settings Configured for JDK 11

Please ensure your project is using JDK 11. Go to File | Project Structure... and under Project SDK select 11 if it is available. If not, click New and select the folder in which JDK 11 is installed (on Windows something like C:/Program Files/Java/jdk-11.x.x). If you cannot find JDK 11, please make sure it is installed.

Also be sure to change the Project language level to 11. Your Project Structure should look like this:

Screenshot: Project Structure with JDK 11

Click File | New | Module from Existing Sources... then select build.gradle in your project. Click OK

From here, change the Gradle JVM to JDK 11. Your dialog box should look like this:

Screenshot: Import Module from Gradle

Once everything looks correct, click OK. This will take some time but after finishing you should now have Gradle integrated with IntelliJ.

Opening Files; Managing Multiple Files

You can open multiple files in IntelliJ by double-clicking each of them from the Project View pane. Once you have multiple files open, you can switch between them quickly by holding down Ctrl and hitting Tab to bring up a dropdown box of open files, and then using the arrow keys to select the file whose editor you wish to bring into focus. You can also navigate through different files using the tabs on top of the editor pane.

Creating New Files

New Java files

To create a new Java source file (with the .java extension), right click on the package you want to add the file to New » Java Class. A window will pop up, asking you for the name of the class. Choose a name for your class (e.g. MyClass) Type this name in the "Name" field and click Finish.

(If you want your new class to be executable, it will need a main method.)

Screenshot: New Java Class

New Text files

There is a similar procedure for creating new non-Java files such as text files. Right click on the directory you want to add the file to New » File. In the resulting dialog box, type the desired filename. If you want to create a new directory, you can do so by appending the directory name in front of your desired filename. For example, if you want to create a file problem0.txt in the directory hw1/answers, but the answers directory does not yet exist, you can choose hw1 as the parent directory, and then type answers/problem0.txt as the file name, and IntelliJ will create the new directory and file for you.

Editing Java Source Files

Here are some useful actions that you can perform when editing Java code:

Autocompletion

Autocompletion is the ability of an editor to guess what you are typing after you type out only part of a word. Using autocompletion will reduce the amount of typing that you have to do as well as the number of spelling mistakes, thereby increasing your efficiency.

IntelliJ continuously parses your Java files as you are editing, so it is aware of the names of variables, methods, etc... that you have declared thus far.

CTRL+Space can be used to autocomplete most things inside the IntelliJ Java editor. For example, if you have declared a variable named spanishGreeting in the current class, and have typed the letters spanishGree in a subsequent line, IntelliJ can infer that you mean to type spanishGreeting. To use this feature, press CTRL+Space while your cursor is at the right of the incomplete name. You should see spanishGree expand to spanishGreeting.

IntelliJ can also help you autocomplete method names. Suppose you have a variable myList of type List, and you want to call the method clear. Begin typing "myList." — at this point, a pop-up dialog will display a list of available methods for the type List, and you can select the appropriate method with the arrow keys. You can force the popup to appear with CTRL+Space.

Organizing Imports

You can press CTRL+ALT+o to organize your imports in a Java file. IntelliJ will remove extraneous import statements and try to infer correct ones for types that you refer to in your code but have not yet been imported. (If the name of the class that needs to be imported is ambiguous – for example, there is a java.util.List as well as a java.awt.List – then IntelliJ will prompt you to choose which one to import.)

Viewing Documentation

Although you can directly browse the Java 8 API and other documentation at the Oracle website, it is often useful to be able to cross-reference parts of your code with the appropriate documentation from within your editor.

Note that you need to generate the API documentation locally before you can view docs for classes in the assignment.

IntelliJ

IntelliJ provides multiple ways to look at documentation of code directly from the IDE. Their website contains documentation on the same. Click here to view this documentation.

If you are adding documentation of code that is written by you, you will need to prepend the file location with file:///.

Using Git with IntelliJ

Please read about version control and git here first.

Pulling Changes from GitLab

Pulling from git takes all the changes from your GitLab repository and brings them onto your machine.

To pull changes, choose VCS | Git | Pull. The Pull Changes dialog will open. You can usually leave all the options as default and click Pull to fetch and apply changes from the remote repository. If there are merge conflicts of any sort, you will be notified.

Commiting Changes In IntelliJ

Commiting changes allows you to create checkpoints of your homework progress as you go. These commits will later be pushed to git.

To commit in IntelliJ, click the IntelliJ Commit Button button in the top right of the window, or press Ctrl+K. The Commit Changes dialog box should appear. In here, you can select which files you would like to commit and leave a commit message at the bottom. This message can be anything you choose, but we recommend using informative descriptions of exactly what was changed. After writing your message and choosing your changes, click Commit. Please note that your changes have not been uploaded to GitLab. To do this, we need to push

Pushing Commits to GitLab

After you have created a commit, you must push it in order for it to appear in your GitLab repository. This can be done by pressing Ctrl+Shift+K or by choosing VCS | Git | Push from the main menu. In this dialog, click Push and your changes will be synced with GitLab. If there are any merge conflicts, you will be informed (this should rarely happen as you are the only one pushing code to your repository).

Creating Git Tags in IntelliJ

In CSE 331, we ask you to create tags in order to turn in your homeworks. To create these tags in IntelliJ, go to VCS | Git | Tags.... In this dialog box, enter a name for your tag and choose a commit, or none for HEAD (which is likely the most recent push). Click Create Tag. Now you must push the tag. Press Ctrl+Shift+K or choose VCS | Git | Push in the main menu and then make sure Push Tags is checked. Now click Push. You should always double check the tag exists in GitLab.

Running Automated Tasks with Gradle

Gradle is a build system, which automates development tasks. Gradle can be run from inside IntelliJ or from the command line. To invoke Gradle from the command line, run the command ./gradlew in directory ~/cse331-18au-$USER.

The most common command is ./gradlew build. It runs the "build" task, which checks your program for common errors, compiles your program, runs tests, and generates documentation. Using a build system like gradle is better than you having to remember to run each of those tasks separately. Run ./gradlew tasks to see a list of other tasks you can use.

To run Gradle in IntelliJ there are 2 different tool windows you could run it from:

  1. Using the Gradle tool window on the right side of the IntelliJ. (If you do not have a Gradle tool window on the right side, you can activate by selecting View > Tool Windows > Gradle)
    Screenshot: IntelliJ Gradle Tool Window

    You can select the task you want to run under each folder. For example, the command ./gradlew build on the command line is equivalent to selecting build > build in the tool window. For this class, most of the tasks you are able to run are under build, validation, and other.

    You can also run the task you want by clicking on the Execute Gradle Task icon, and typing in the name of the task you would like to execute.

  2. Using the IntelliJ Terminal tool window at the bottom of IntelliJ.
    Screenshot: IntelliJ Terminal Tool Window

    You will be able to run most ./gradlew command line targets on this terminal.

Compiling Java Source Files

You must compile your source code before running it. The javac compiler is used to transform Java programs into bytecode form, contained in a class file. Class files are recognized by their .class extension. The bytecode in class files can be executed by the java interpreter.

IntelliJ is set up by default to automatically recompile your code every time you save. Classes with compile errors are marked in the Project View with a red underline.

If your file is saved and IntelliJ says that it does not compile but you believe that it should, make sure that all of the files on which your file depends are saved and compiled. If that does not work, try refreshing your project or using Build » Rebuild Project to force IntelliJ to recognize the latest versions of everything.

Running Java Programs

Once you have compiled your source code into class files, you can execute it with the Java interpreter.

To run a program, right click on the Java source file containing the main() method and choose Run 'FILENAME' where FILENAME is the file with the main() method.

There is also a button near the top-right-hand side of the IntelliJ window that looks like a
green 'play' button which will re-run the last application (or JUnit test, see below) that you ran.

Testing Java Programs with JUnit

JUnit is the testing framework that you will use for writing and running tests.

For more information, visit:

Running JUnit Tests

JUnit is normally integrated with IntelliJ, but since we are using Gradle, we must tell IntelliJ to delegate work to Gradle.

  1. On the main menu, choose File > Settings for Windows and Linux or IntelliJ IDEA > Preferences for macOS
  2. Navigate to Build, Execution, Deployment > Build Tools > Gradle > Runner
  3. In the "Run tests using:" dropdown menu, select "Gradle Test Runner". Be sure to leave "Delegate IDE build/run actions to gradle" unchecked.

Now, if you run any tests under src/test/java/hw*, it will use Gradle to run it. To run any specific test file:

To run all of the tests in your test suit, select Verification > test in the IntelliJ Gradle tool window.

A test result window should pop up near the bottom of the screen momentarily and run all the tests. You can double-click on failed tests to jump to the code for that test. When you're done inspecting the JUnit results, you can close the JUnit pane.

CSE 331 JUnit Framework

Because your JUnit tests will likely have different class and method names than those of your classmates, there needs to be a standardized way of accessing every student's tests. Thus, each assignment comes with the JUnit test classes hwN.test.SpecificationTests and hwN.test.ImplementationTests. You will load all the JUnit tests you wrote in one of these two test suites.

hwN.test.SpecificationTests, as it name suggests, should contain only specification tests — that is, those tests that check only for features implied by the specification. Consequently, your specification tests should be valid tests for any other person's code that claims to satisfy the same specification, even if that implementation is inherently very different.

Conversely, hwN.test.ImplementationTests should contain implementation tests — that is, those tests that test only details that are specific to your implementation.

As an example, suppose you were implementing the following specification:

/**  Frobs the blarghnik.
  * @spec.requires b != null
  */
public void frob(Blarghnik b);

A specification test should never pass in a null parameter to this method — this would violate the specified pre-condition. However, your particular implementation might check for the null parameter and throw a NullPointerException. Your implementation test can safely exercise this case by passing in null.

Similarly, an iterator specification which does not specify the order in which elements are returned indicates that no specific order should be assumed in a specification test. Your implementation may happen to keep elements in a sorted list, and so your implementation test may wish to check that the elements returned by the iterator are sorted.

Before your submit each assignment, you should run tests with ./gradlew build and validate your assignment with ./gradlew build.

Using javadoc to generate specs

The javadoc tool produces API documentation (in HTML form) from source code annotated with special comments.

To run the Javadoc tool, issue this command:

./gradlew javadoc
You can find the generated API documentation, in HTML form, under build/docs/javadoc.

You can also generate API documentation in IntelliJ by selecting Tools > Generate Javadoc...

If IntelliJ fails due to unknown tags, you will need to add the tags to IntelliJ.

Javadoc tags

Your Java code comments contain "tags", which are introduced by an at-sign (@). The Javadoc tool formats these specially in the HTML output.

We have extended the javadoc tool to recognize additional CSE 331 tags, in adition to the standard tags. These additional tags declare specification fields for classes and requires, modifies, and effects clauses for methods. Note that all Javadoc tags must appear after all non-tag comments for classes and methods.

Customizing IntelliJ

You may need te specify the path to the git executable: In the Settings/Preferences dialog (Ctrl+Alt+S), select Version Control | Git in the left pane.

It is bad style to have tab characters in code files, because they display differently for different people. (Pressing the Tab key while using your editor is great, but that key should should insert spaces.) In IntelliJ IDEA, make sure that the Editor >> Code Style >> Default Indent Options : Use tab character checkbox is not selected.

331 extended Javadoc tags

IntelliJ will warn you about unrecognized the 331 Javadoc tags (@spec.*). There are two ways to eliminate the warnings.

  1. Disable the editor's Javadoc inspection.
  2. Add each of the extended tags as a known tag for IntelliJ.

    Using the keyboard shortcut:

    Using the settings panel

After you have done one of the above, the warnings for the extended tags will go away.

Google Java Format Plugin

Optionally, you could install the Google Java Format plugin to IntelliJ that will reformat your code using the google-java-format tool. This is the same tool that ./gradlew reformat and ./gradlew checkFormat uses to run on your source code.

  1. On the main menu, choose File > Settings for Windows and Linux or IntelliJ IDEA > Preferences for macOS
  2. Navigate to Plugins
  3. In the search bar type "google-java-format" and select "Search in repositories".
  4. Install the plugin and restart IntelliJ. After you restart, you should be prompted to enable google-java-format for your project. Select "enable".

Troubleshooting IntelliJ

If the staff provides a new version of a library, IntelliJ will not automatically know about the library's new symbols (classes and methods). As a result, IntelliJ will not do completion and may issue warnings about them. To resolve the problem:

  1. git pull
  2. ./gradlew build
  3. In IntelliJ's Gradle window (View > Tool Windows > Gradle), click the refresh button at the end to refresh all libraries.