We’ll have a look at how to view known vulnerabilities in your Maven or Gradle projects, how to get more information about the known vulnerabilities in a specific dependency and how to remediate these vulnerabilities inside IntelliJ IDEA Ultimate if a new version with a fix is available.
In this tutorial, we’re going to take a look at managing dependencies in IntelliJ IDEA. We’ll look at different ways to add dependencies to your project, and how to add, upgrade and remove dependencies using Package Search.
Add dependencies
There are several ways to add new dependencies to your project.
From the build file using copy-paste
You have probably copied a dependency from Maven Repository (or another website) and pasted into your build file.
For example, we can copy the Gradle format for this dependency and paste it into our build.gradle file.
Or, if we are using Maven, we can copy the Maven xml format into our pom.xml.
Did you know that if you copy-paste a Maven XML dependency into your build.gradle file, IntelliJ IDEA automatically turns it into the correct format for Gradle?
From the build file using code completion
We can also add dependencies to our build file using code completion. For example, let’s add a new dependency to our pom.xml.
We see that IntelliJ IDEA autocompletes the dependency xml, and we can search for the dependency we want, in this example AssertJ. If needed, the version number will also be added. Since this is a test dependency, we need to add the test scope, still using code completion.
Code completion works in Gradle too, as you can see below.
From the build file using code generation
We can also use code generation from the build file to add dependencies. In the build file, the pom.xml in a Maven project, invoke Package Search using ⌘N (on macOS) or Alt+Insert (on Windows & Linux) and in the menu that opens, select Add dependency. This will open the Dependencies tool window.
Note that if we are using Gradle, we can do the same in our build.gradle file.
From the Dependencies tool window
Alternatively, we can open the Dependencies tool window directly. There is no shortcut to open the Dependencies tool window, so we can either use Recent Files, ⌘E (on Mac) or Ctrl+E (on Windows/Linux), and type in “dependencies” to open the Dependencies tool window.
Alternatively, we can open it by clicking Quick Launch in the bottom-left and selecting Dependencies.
In the Dependencies tool window, we can search for a dependency. For example, let’s search for AssertJ.
Note that we can select a scope for this dependency. The names of the scopes are based on the build tool with which you are working. Since this is a test dependency, and we are using Gradle in this project, we can set the scope to testImplementation.
We can also select the version we want to use.
We can do the same in Maven.
Note that the names of scopes for Maven are different from Gradle. In Maven, we can set the scope for a test dependency to test.
When we click Add, we see that the dependency is added to the build file.
If the version number is shown in red, that means IntelliJ IDEA hasn’t downloaded this library before. Click Load Maven Changes so IntelliJ IDEA will update its dependencies based on the changes to the pom.xml or build.gradle file.
Go back to the Dependencies tool window and clear the search box by clicking the x on the right-hand side. You’ll see the project’s dependencies are updated with your new dependency.
Next, let’s look for jackson-databind. We see that there are several versions available. Since we have selected Only stable, only stable versions are shown in the list.
If we uncheck this option, we see that the list of versions also includes the release candidates.
For production code, we probably want to use stable versions, so let’s select the Only stable checkbox again. With this option enabled, IntelliJ IDEA will exclude any dependencies that have no stable versions, and hide them from the list. Now we can select the latest stable version and add this to our project. Let’s also Load Maven Changes again.
Finally, let’s also add a new dependency to the Kotlin module. Let’s switch to the Kotlin module and open the pom.xml for this module. Open the Dependencies Tool Window and search for Ktor.
Notice that some dependencies are marked as Multiplatform.
If we want to see only Kotlin multiplatform dependencies, we can select the Kotlin multiplatform checkbox, as shown below.
When we click Add to the right of the Ktor dependency, we see that Ktor is added to the list of dependencies and to the pom.xml for the Kotlin module.
Upgrade dependencies
We will also need to keep our dependencies up to date. To show you how IntelliJ IDEA can help, we are using this extremely outdated project as an example. In the pom.xml below, we see that several dependencies are marked with squiggly lines underneath them.
IntelliJ IDEA will show the suggestion to upgrade when we hover over the dependency, and we can click the suggestion to upgrade the dependencies.
Alternatively, we can use Context Actions ⌥⏎ (on macOS) or Alt+Enter (on Windows & Linux) to upgrade these dependencies.
We can also upgrade our dependencies using the Dependencies tool window. The Dependencies tool window will tell us if there’s a newer version of a dependency, as we can see here.
We can choose the version to upgrade to by clicking on the version number in the list. Note that we don’t have to use the latest version.
We can also automatically upgrade a dependency to the latest version by clicking Upgrade for that particular dependency.
Or, we can even upgrade all our dependencies at once, by clicking the Upgrade all link.
Remove dependencies
Finally, we can remove dependencies we no longer need. In the Dependencies tool window, let’s remove jackson-databind from the Java module. We select the dependency we want to remove (jackson-databind) and in the Dependency details pane on the right, click the More button (three dots) and select Remove.
We will see that the dependency is removed from the pom.xml and the dependency list. To remove a dependency from the whole project, select All Modules on the left.
Summary and Shortcuts
Now we know the different ways in which we can view our project’s dependencies in IntelliJ IDEA, and the different focus for each view.
IntelliJ IDEA Shortcuts Used
Here are the IntelliJ IDEA shortcuts that we used.
In this screencast, we’re going to take a look at managing dependencies in IntelliJ IDEA. We’ll look at different ways to add dependencies to your project, and how to add, update and remove dependencies using Package Search.
Recently I asked my 8 year old if he would be interested in doing some Java programming with me, and he was. This was such a fun experience, I wanted to share it with you.
Why Java?
In the past, we have done part of a Scratch course by Felienne. So I know there are other programming languages out there that are made specifically for kids. However, I wanted to show him something that is a bit more like what his dad (also a software developer) and I do all day.
It was an explicit decision on my part not to bore him with Java syntax just yet, but instead to focus on what the program should do and getting a bit of understanding of how programming works. While most of the code was written by me, the behavior of our little application was based on our collective ideas.
Hello world!
We used IntelliJ IDEA Community Edition 2022.3, and I opened a new project using Java and Maven, thinking we would get started with a simple Hello World program (as you do).
New Project wizard
It turned out that IntelliJ IDEA already includes the Hello World example when opening a new project, which was a nice surprise.
Hello world!
First, I asked him to run the program by clicking the run button (green triangle) in the gutter. He asked me what it means to “run” the program, so I explained this means having the computer execute the program, doing the thing the code tells it to do.
When we ran the program, we saw that the text “Hello world!” was printed in the command line. I tried explaining that “public static void main” is the main method, telling the computer where to start, but to be honest I’m not sure he understood that just yet.
Asking for user input
Next, I asked him whether he would like to print something else and what we would need to change in order to do so. He knew we had to change the green text (the String) to something else. He changed the word “world” in this String to his name and ran the program again.
My next suggestion was to ask the user for their name so the computer would be able to greet other people too. Here I briefly explained we would need some way to capture the user’s input. To do so, I added a Scanner and the variable “name”. After I made these changes, he ran the program and tested that it worked when he input his name.
Asking for user’s name
Next, we discussed what else to ask the user. He wanted to ask for their favorite color and provide the “computer’s” favorite color as a response to their answer. We added another question and captured another variable to return to the user.
Asking for name and favorite color
Selecting a language
Of course, while the kids speak some English, it is not their native language. So we decided to translate the output to Dutch to make it a little easier for him to understand. Next, he suggested we should give the user the option of using the program either in Dutch or in English. We started with a simple if/else statement and duplicated code blocks of asking the same questions in either Dutch or English, depending on the input.
Selecting a language
He was quick to point out that we should think about what to do if the user provided a language or input we didn’t know. Good question! So we proceeded to add logic for that as well.
Validate input
Next, we ran the program several times to check that it worked for each valid option, as well as (multiple) invalid options.
Next steps
Finally, we discussed what potential next steps we could take with this program. We had several ideas:
He wanted to know if it would be possible to remove the duplication somehow; for example, by getting the Dutch or English text from somewhere so we wouldn’t have to duplicate all the code. In our current program, the code for the Dutch version and English version is duplicated, meaning that for every additional question we want to ask the user, we have to make sure to duplicate that.
In one of my tests, I showed him that the computer would just capture and return whatever the user’s input was. The example I used was to answer “Hello, what is your name?” with a full sentence: “Hi, my name is Marit” to which the computer would reply “Hello Hi, my name is Marit, what is your favorite color?” which is a bit weird. So that is something to think about.
Takeaways
The most important thing is that we had fun. He was motivated to add new things to the program and to test that they worked. My choice to not focus on the details of Java syntax, but on the general program instead seems to have worked because he had fun and wanted to continue. He is already asking me when we can do this again, and has ideas of what we could do next.
The program was written based on his ideas and he did write some of it himself, mainly the Strings and some of the “System.out.println()” lines, after I showed him how to use IntelliJ IDEA live templates to do so; if you type “sout” and press Enter (or Return on Mac), IntelliJ IDEA will expand that to “System.out.println()” which he thought was very helpful.
What I noticed was that he was able to think about what the program should do, and had a rough understanding of how the code worked. Once we were done, he was able to explain our little program to his dad, and pointing to the relevant points in the code while explaining what they did. So I have the impression he has some understanding of how it works.
Overall, we had fun together coding and it was awesome to see how his mind worked when thinking about what the program should do and how, and how to test it. We are very much looking forward to continuing our little experiment.
In this blogpost we’re going to take a look at different ways to view your external dependencies in IntelliJ IDEA.
Introduction
If you’re working on a real-world application, your project will probably use external libraries and frameworks. Occasionally, you might want to see which dependencies your project uses, for various reasons.
There are several ways to view dependencies in IntelliJ IDEA. Each view has a different focus.
Dependency management config file
You can find direct dependencies in the dependency management config file. Direct dependencies are the dependencies that your project depends on directly. They are declared in the dependency management config file.
One example is this pom.xml in a Maven project.
Maven pom.xml file
Another example is the build.gradle in a Gradle project.
Gradle build.gradle file
Note that the dependency management config file includes only declared dependencies and not their transitive dependencies (or the dependencies that these declared dependencies depend on).
Project tool window
In the Project tool window, ⌘1 (on Mac) or Alt+1 (on Windows/Linux), under External Libraries we can see all the JAR files needed by our application, including the transitive dependencies. However, we cannot tell the difference between direct dependencies and transitive dependencies. One declared dependency might bring in multiple JAR files.
Project tool window
Build tool window
To see direct dependencies and their transitive dependencies, we can look in the Build tool window. There is no shortcut to open the Build tool window. We can open it by clicking Quick Launch in the bottom-left and selecting Gradle, or Maven depending on what we’re using.
Open the Maven Build Tool Window in the Quick Launch menuOpen the Gradle Build Tool Window in the Quick Launch menu
Alternatively, we can open it by using Recent Files, ⌘E (on Mac) or Ctrl+E (on Windows/Linux), and typing “gradle” or “maven”, or the name of your build system.
Open the Gradle Build Tool Window using the Recent Files popup
Open the Maven Build Tool Window using the Recent Files popup
The Build tool window shows you each IntelliJ IDEA module separately, and each module’s “Dependencies” folder shows you all your dependencies in a hierarchical structure. We can expand our dependencies to see their transitive dependencies.
Finally, we can view and manage dependencies in the Dependencies tool window. The Dependencies tool window becomes available when the current project has at least one supported module. All types of dependencies are supported for Maven. For Gradle only a top level dependencies { } block is supported in the build script.
Since there is no shortcut to open the Dependencies tool window directly either, we can again use Recent Files, ⌘E (on Mac) or Ctrl+E (on Windows/Linux), and type in “dependencies” to open the Dependencies tool window.
Open the Dependencies Tool Window using the Recent Files popup
Alternatively, we can open it by clicking Quick Launch in the bottom-left and selecting Dependencies.
Open the Dependencies Tool Window in the Quick Launch menu
Here we can see our project’s direct dependencies. Select “All Modules” to see the dependencies for all modules, or select an indivual module to see the dependencies for that specific module. The Dependencies tool window shows direct dependencies, and not their transitive dependencies.
Dependencies Tool Window
We can see details about a selected dependency in the dependency details pane.
Dependency Details Pane
The dependency details pane displays the information about the selected dependency, such as:
Repository or repositories where it’s available, for example Maven Central
A description if it is available
GitHub information if the dependency sources are hosted on GitHub
The licence under which an open source library is available
A link to the project website, documentation and readme
List of usages in the current module.
Authors if available
Supported Kotlin or Multiplatform platforms if it is a Kotlin Multiplatform dependency
Summary and Shortcuts
Now we know the different ways in which we can view our project’s dependencies in IntelliJ IDEA, and the different focus for each view.
IntelliJ IDEA Shortcuts Used
Here are the IntelliJ IDEA shortcuts that we used.
If you’re working on a real-world application, your project will probably use external libraries and frameworks. Occasionally, you might want to see which dependencies your project uses, for various reasons. There are several ways to view dependencies in IntelliJ IDEA. Each view has a different focus.
This article was published on Foojay.io on October 11, 2022.
In this article, we will take a look at ways to level up your presentation skills with IntelliJ IDEA.
Presentation Assistant plugin
Our first tip is to use the Presentation Assistant plugin. The Presentation Assistant plugin will show which shortcuts are being used.
To install the plugin, open Preferences using ⌘, (on Mac) or Ctrl+Alt+S (on Windows/Linux). Go to Plugins and search for “Presentation assistant” on the Marketplace tab. Click Install and when it’s done, click OK to apply the changes and close the dialog or click Apply to keep the dialog open.
To configure the Presentation Assistant plugin, go back to Preferences and go to Appearance & Behavior > Presentation Assistant.
Here we can configure font size, duration, alignment, and which keymaps to show. We are using macOS, with Windows as the alternative keymap. We have also configured the Presentation Assistant plugin to show the shortcuts at the top of the screen.
Presentation Mode
When presenting, you can use Presentation Mode. The IDE switches to full screen and everything is hidden except for the main editor window. The font size is increased, so it is easier to read from a distance.
You can switch to Presentation Mode by clicking View > Appearance > Enter Presentation Mode.
If needed, the font size in Presentation Mode can be configured in Preferences > Appearance & Behavior > Appearance. Scroll down to Presentation Mode, and font size and set the font size you want. Click OK to apply the changes and close the dialog or click Apply to keep the dialog open. Click Cancel to discard the changes and close the dialog.
We can also open Presentation Mode using short-cuts. Open the Quick Switch Scheme using ⌃ BackTick (on Mac) or Ctrl+BackTick (on Windows/Linux). Use the arrows to select View Mode and then select Enter Presentation Mode.
We can use Quick Switch Scheme again to Exit Presentation Mode.
Mouse Zoom
To enable mouse zoom, you need to turn it on explicitly. Go to Preferences > Editor > General and select Change font size with Command+Mouse Wheel (on Mac) or Change font size with Control+Mouse (on Windows/Linux). Click OK to apply the changes and close the dialog or click Apply to keep the dialog open.
Now we can use Command+Mouse Wheel (on Mac) or Control+Mouse Wheel (on Windows/Linux) to zoom in or out. While we are using mouse zoom, a popup appears containing the current font size on the left and a link to reset to the original font size on the right. Click the link to reset the font size.
Font
To configure font and font size, go to Preferences > Editor > Font. We can select the font we want to use, and set the font size.
When presenting in person, make sure the font can be read from a distance. If possible, check out the room where you’ll be speaking, do your setup before your talk, and walk to the back of the room to check if the code is readable.
Theme
By default, IntelliJ IDEA uses the Darcula theme. To change it, go to Preferences > Appearance & Behavior > Appearance.
Select the UI theme from the Theme list:
IntelliJ Light is a traditional light theme for IntelliJ-based IDEs
macOS Light or Windows 10 Light is an OS-specific light theme available as a bundled plugin
Darcula is the default dark theme that we’re using here
High contrast is a theme designed for users with color vision deficiency
Which theme to use depends on your personal preference. When presenting in front of an audience, you may want to take into account how light or dark the room is. If possible, try different themes and walk to the back of the room to see which one works best before your presentation. When sharing your screen during an online meeting, you may also want to check with teammates which theme works best.
Tool windows
We recommend closing all unused windows so we can focus on the code we’re looking at. Use Command + Shift + F12 (on Mac) or Control+Shift+F12 (on Windows/Linux) to hide all tool windows.
We can always reopen them using shortcuts. Here are the shortcuts to some of the most used windows:
To open or close the Project Tool Window use ⌘1 (on Mac) or Alt+1 (on Windows/Linux)
To open or close the Commit Tool Window use ⌘0 (on Mac) or Alt+0 (on Windows/Linux)
To open or close the Terminal Tool Window use Alt+F12
To open or close the Git Tool Window use ⌘9( on Mac) or Alt+4 (on Windows/Linux)
To open or close the Run Tool Window use ⌘4( on Mac) or Alt+4 (on Windows/Linux)
To open or close the Debug Tool Window use ⌘5( on Mac) or Alt+5 (on Windows/Linux)
You can also use keyboard shortcuts to stretch the active window. Go to the relevant window, and use ⌃ ⌥ ← or ⌃ ⌥ → (on Mac) or Control+Alt+Shift+Left or Control+Alt+Shift+Right (on Windows/Linux) to stretch the window left or right. This also works with the tool windows at the bottom, using the up or down arrows to stretch the window up or down.
Find action
If you want to do something, but don’t remember the shortcut or menu option, use Find Action. Press ⇧⌘A (on Mac) or Control+Shift+A (on Windows/Linux) to open the Find Action dialog. Search for the action you want, and select the relevant action.
For example, let’s use Find Action to apply soft-wrap.
Soft-wrap
When using a file that has long lines, we can prevent horizontal scrolling by using soft-wrap. Let’s use Find Action to enable soft-wrap. Press ⇧⌘A (on Mac) or Control+Shift+A (on Windows/Linux) to open the Find Action dialog, and search for “soft-wrap”.
We get the option to turn on soft-wrap, which will be for this file only. You can click this option to turn soft-wrap on or off.
Alternatively, we can configure soft-wrap. Let’s select “Soft wrap these files“, which will soft-wrap several types of text files. Click OK to apply the changes and close the Preferences dialog.
Shortcuts
We recommend using shortcuts as much as possible when presenting. This is easier to do during a presentation than using a mouse or trackpad, especially if you get nervous and your hands might get slippery. There are several ways to learn shortcuts.
Find Action lets you search for commands and settings across all menus and tools.
Key Promoter X is a plugin that shows a popup notification with the corresponding keyboard shortcut whenever a command is executed using the mouse. It also suggests creating a shortcut for commands that are executed frequently.
If you are using one of the predefined keymaps, you can print the default keymap reference card and keep it on your desk to consult it if necessary. This cheat sheet is also available under Help > Keyboard Shortcuts PDF.
Let’s take a look at some shortcuts for navigation.
Navigation
We can use several shortcuts to navigate around a project:
We can Find a class using ⌘ O (on Mac) or Ctrl+N (on Windows/Linux).
We can move the caret to a method and use ⌘ B (on Mac) or Ctrl+B (on Windows/Linux) to go to the declaration or usages.
We can also navigate backwards by using ⌘ [ (on Mac) or Ctrl+Alt+Left (on Windows/Linux), or navigate forward: ⌘ ] (on Mac) or Ctrl+Alt+Right (on Windows/Linux).
Use ⇧ ⌘ E (on Mac) or Ctrl+Shift+E (on Windows/Linux) to find Recent Locations.
Or find Last edited location with ⇧ ⌘ ⌫ (on Mac) or Ctrl+Shift+Backspace (on Windows/Linux).
Finally, we can find Recent Files using ⌘ E (on Mac) or Ctrl+E (on Windows/Linux).
Bookmarks
Another way to navigate through code, is to use bookmarks. Press F3 (on Mac) or F11 (on Windows/Linux) to create an anonymous line bookmark.
To add a mnemonic line bookmark, press ⌥ F3 (on Mac) or Control+F11 (on Windows/Linux). In the popup that opens, select a number or a letter that you want to use as an identifier for this bookmark. Press ⏎ (on Mac) or Enter (on Windows/Linux) to save the bookmark. To bookmark files, packages, folders, and modules, right-click the item you want to bookmark in the Project Tool Window, and add an anonymous bookmark (F3 (on Mac) or F11 (on Windows/Linux)), or a mnemonic bookmark (⌥ F3 (on Mac) or Control+F11 (on Windows/Linux)).
There are several ways to navigate between bookmarks. Press ⌘ F3 (on Mac) or Control+F11 (on Windows/Linux) to open a popup showing bookmarks and select the desired bookmark with the keyboard and press ⏎, or select the corresponding digit or letter for a mnemonic bookmark.
To jump straight to a mnemonic bookmark, hold ^ (on Mac) or Control (on Windows/Linux) and press the mnemonic digit or letter on the keyboard.
Summary and Shortcuts
Now we know several tricks that will level up our presentation skills with IntelliJ IDEA.
IntelliJ IDEA Shortcuts Used
Here are the IntelliJ IDEA shortcuts that we used.
When you work in a team, you may come across a situation when somebody pushes changes to a file you are currently working on. If these changes do not overlap, the conflicting files are merged automatically. However, if the same lines were affected, Git cannot randomly pick one side over the other, and asks you to resolve the conflict. In this screencast, we’re going to take a look at resolving merge conflicts.
Open source software is everywhere. Most likely you are using some open source projects either at work and/or in your side projects.
Pros and cons of using dependencies
One of the upsides of using Java as a programming language, is that there are libraries and frameworks available to do many of the things we want to do in our projects, but don’t necessarily want to write ourselves. Using existing libraries and frameworks helps us deliver business value faster.
Unfortunately, there are also downsides to using external dependencies. The most dangerous being when security vulnerabilities are found in libraries many of us use, like the Log4Shell vulnerability in the log4j logging library that was disclosed in December 2021 and the Spring4Shell vulnerability in Spring in March 2022. These vulnerabilities were so severe that we had to patch all our services ASAP. Even if the version of a dependency you use does not have any known vulnerabilities, you might need to update them for other reasons.
In addition, adding dependencies to your project also has an impact on the size of your binary. For example, Brian Vermeer has created a demo to show the number of lines of code written versus number of lines pulled in by Spring. Granted, he admits that “this was the most useless Rest endpoint you could ever write”, but this demo clearly shows how the code pulled in by dependencies can overshadow to amount of code you write yourself.
A balancing act
This means we have to think carefully about which dependencies we want to use. Some developers try to add little or no external dependencies to their projects. This is one way to avoid the downsides mentioned above. Another argument may be that it gives you more control over the code in your project. Of course, the downside here is that you have to write everything yourself, which might not always be the best idea. For example, I’d rather use JUnit and Mockito than write my own testing and mocking frameworks. On the other hand, we shouldn’t just add any library or framework, as we’ll have to not only implement them now, but also maintain them over time. Or even remove them in the future, which is not always easy. Some projects, like Lombok or Reactor, will be present throughout your code base and hard to remove should you ever want to (for example, when moving to Kotlin & coroutines).
Most of us will be somewhere in the middle; we don’t want to write everything ourselves, and we will use certain frameworks and libraries that offer us some useful functionality, but we also want to make sure we can continue to maintain our project without having to (urgently) update dependencies or rewrite our code because something is vulnerable or otherwise outdated.
What to consider when selecting dependencies for your project
The best time to check your dependencies is before you add them. The second-best time is now. So take a critical look at any dependencies you’re adding or already using and consider the following:
Do we really need this dependency?
To make it worth it to use a dependency, it has to solve our problem and do so without adding new problems. We need to consider if the project fits our needs. We can do so by reading the documentation, and by seeing what experience other users already have with a particular tool. Keep in mind that, just because other users are enthusiastic about a particular library, that doesn’t necessarily mean it’s right for you. Their context or use case might be different from your own. There might be other libraries out there offering similar functionality that are a better fit for your project.
Also consider how much of the library you’ll actually use. If it is only a small part, consider other solutions. For example, do we really need to import StringUtils to use it for one or several String functions, or can we write them ourselves? (And, if we moved to Kotlin since then, we might be able to replace them with standard Kotlin functionality.) Or are we already using another library for this particular problem? For example, we won’t need gson if we are already using jackson (or vice versa)?
Is the project well maintained?
If a project is no longer maintained, we run the risk of having to urgently replace it if security vulnerabilities are found. To see if a project is actively maintained, you can check when the last release was, and how frequently new versions come out; you can find this information for example on Maven repository. You can also check when the last commit was, and whether the project is maintained by one person, or a group of active maintainers. A project that depends on one particular person runs the risk of becoming unmaintained if that person no longer has the time and energy to maintain that project. Maintaining a successful open source project can be a thankless task and maintainer burnout is real. With multiple maintainers the load and risk can be shared. You might want to look into how many open Issues and Pull Requests (PR) there are, and the interaction on those Issues & PR’s. You can find this information on GitHub or wherever the code for the project is kept.
How popular is the project?
A popular project might have more stars, watches and forks on GitHub. Although these metrics don’t necessarily mean that people are using it; they might have starred it to try it out later. These metrics might be useful when comparing similar tools, but not necessarily when comparing different tools.
A widely used project will likely have more people talking and writing about it. Having a large number of users means more people who are able to help out others. It also means there are more potential contributors, but unfortunately a high number of users doesn’t always translate to a high(er) number of contributors. And just because a project is popular doesn’t mean it’s right for you.
What is the community like?
Consider whether the community is friendly and welcoming. How do they interact with their users and (potential) committers? How do they respond when issues are reported? Do they review PR’s quickly and offer constructive feedback? Friendly maintainers often make for a more friendly community. They might be active in official support channels like Slack, Gitter or mailing lists, or help answer questions on StackOverflow, write talks and blog posts or find other ways to share their knowledge.
Is it easy to use?
Finally, consider whether the project easy to implement & use, and whether you like using it. Developers have personal preferences with regard to almost everything in software development, including which tools they like to use. If a popular framework doesn’t work for you, and you have options, choose something else! Part of whether a project is easy to use might include how well documented a project is. Good documentation can help make it easier to use. Consider looking at the official documentation, as well as blogs and content created by users. The official documentation will (hopefully!) explain how a project is meant to be used.
What is the latest stable version? Are there any open vulnerabilities?
Once you’ve decided to import a dependency, make sure to add the latest stable version. We don’t want to add an older or unstable versions that we then have to update. And we definitely don’t want to import a dependency that has known vulnerabilities that have not (yet) been fixed! We want to keep our software secure and maintainable.
Where to find this information
As mentioned, there are several places where we can look for information about a dependency we are considering. One is Maven repository where we can find open source packages, their versions, whether there are any known vulnerabilities and more.
For example, when we look at Jackson Databind on Maven repository we see a list of versions and their release dates, we see the number of usages by other artifacts for each version, and we see a warning in red for versions with known vulnerabilities.
Jackson Databind on MvnRepository
When we look at the details of a version with known vulnerabilities (Jackson Databind v2.13.2 in this example), we see the CVE number for this vulnerability which links to the details for this CVE). There is also a warning in yellow that there is a new version for this artifact with the link to that version.
Details for a vulnerable version of Jackson Databind
Another is to find the project’s code on GitHub, to look at the code itself, see when the latest commit was, look at open Issues and PR’s, and check Insights for more details on contributors, frequency of commits and other activity.
Jackson Databind repository on GitHub
We can look for official documentation and read (or at least scan) it to see whether the project is a good fit for us, and whether it is well documented. Other information might take a bit more effort to find: Go into the support channels and ask questions. Search for blog posts (or YouTube videos, if you prefer) and other places where you can find information. We might even check StackOverflow to see whether there is a tag for this dependency, how many (open) questions there are, etc.
JetBrains has created a Package Search website that can be used to search for Java and Kotlin libraries and get a lot of this relevant information, including the latest (stable) version, links to relevant tags on StackOverflow, links to the official docs and the code, and if the project is on GitHub the number of stars, watchers and forks on the Information tab. A list of versions (similar to the one on Maven repository) can be found on the Versions tab.
Carefully consider which dependencies to use, taking into account at least some of the things we have discussed here. The best time to do so is before you start using them. But don’t forget to periodically check the dependencies in your existing codebase to see if you still use them, and still want to use them based on the considerations above. Don’t be afraid to remove them if they no longer bring you value.
In this blog post, we will look at some standard Maven commands that can help us manage our dependencies and keep them up to date. These are useful to see both direct and transitive dependencies used in the project, look for version updates of dependencies and plugins, and look for unused dependencies that may be removed. All of these can be useful to keep our dependencies up to date.
Pre-requisites
For the examples in this post, we are using the following tools and versions:
IntelliJ IDEA Community Edition 2022.2.1 – which you can get here
Example project from GitHub (Note: this is an outdated & unmaintained project, which makes it useful to show how to find outdated dependencies)
Maven 3.8.6 (optional, see note below) – Install Maven
Note: Maven wrapper
The project we are using in this example includes a Maven wrapper. If the project you are working on does not have a Maven wrapper, you will need to have Maven installed on your local machine. To add Maven wrapper to your project, run the following command in your terminal: mvn wrapper:wrapper and commit the result. Now anyone who uses the project can use the Maven wrapper without having to install Maven locally, and using the same Maven version.
Using Maven to display dependency updates
We can use Maven to check if there are updates available for the dependencies we are using in our project. Run the following command in your terminal: ./mvnw versions:display-dependency-updates.
This will display a list of dependencies for which newer versions have been found.
Display dependency updates
As you can see, there are quite a few dependencies that need to be updated in this project. The reason is that this is an old project that was created from a tutorial years ago and not maintained since. The upside is that it is a great project to use as an example for finding outdated dependencies.
Using Maven to display plugin updates
The same is possible for plugins. Check which plugins can be updated by running the following command in your terminal: ./mvnw versions:display-version-updates.
On the example project, this provides the following result:
Display plugin updates
This project doesn’t really use a lot of plugins. Your actual projects might, so I wanted to include this command here.
Overview of dependencies: dependency-tree
To see all the dependencies you are using in your project, run the following command in your terminal: ./mvnw dependency:tree. This will return a list of the dependencies declared in this project, and their transitive dependencies:
Dependency tree
Of course, you can also find the declared dependencies in your pom.xml, but it’s good to have an idea of which transitive dependencies they bring in.
Filtering the dependency tree
The dependency tree for this example project is rather small, like the project itself. Your actual projects at work might be much bigger. If needed, you can filter the dependency tree.
To check where a specific dependency is coming from, use the following command: ./mvnw dependency:tree -Dincludes=<groupId>:<artifactId> containing the groupId and artifactId of the dependency you are looking for.
For example, if we would like to see where this project is getting the slf4j dependency, we would run ./mvnw dependency:tree -Dincludes=org.slf4j:slf4j-api. We see that we get this transitive dependency through Hibernate:
Filtering the dependency tree
For more information on filtering the dependency tree, see the Maven documentation.
Effective pom
The effective pom is the POM that results from the application of interpolation, inheritance and active profiles. To generate the effective POM, run the following command in your terminal: ./mvnw help:effective-pom.
When running this command on the the example project, the result will be fairly small, because it is a relatively small project. For a large project, the effective pom will be much bigger. If needed, you can write the effective POM into a log file using the following command: ./mvnw help:effective-pom --log-file log.txt.
Use Maven to find unused dependencies
We can also use Maven to find unused dependencies. Run ./mvnw dependency:analyze on the example project gives us the following results:
Analysing dependencies
We see that we have “Used undeclared” dependencies, like org.springframework:spring-beans. If we search for that dependency, by filtering the dependency tree for that particular dependency using ./mvnw dependency:tree -Dincludes=org.springframework:spring-beans we see that it is a transitive dependency from Spring-webmvc:
Filtering the dependency tree
We also see some “Unused declared” dependencies. If these are dependencies you truly don’t need, it might be a good idea to remove them from your pom.xml. (Note: In this example, JUnit is unused because the tutorial this project is based on didn’t include any tests. If that is the case for your project, consider adding tests instead of removing this dependency!)
Conclusion
Maven offers several ways to help us keep our dependencies up to date. Using the commands above can help us to keep the dependencies we need up to date, and to remove the dependencies we no longer need.