Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Intermediate Java: A Learning Path (Part 1)

DZone's Guide to

Intermediate Java: A Learning Path (Part 1)

Want to learn how to take your Java knowledge to the next level? Check out this post on learning intermediate Java, focusing on practical programming exercises.

· Java Zone ·
Free Resource

Java-based (JDBC) data connectivity to SaaS, NoSQL, and Big Data. Download Now.

You just might have finished reading "Head First Java," or you might have a pretty firm grasp of core Java concepts. However, so far, you have only really focused on one specific technology like Swing. Or, you might be coming from a different programming language, like PHP or Python and want to get your feet wet with Java.

In all cases, the question often is "What should I learn next?"

I think it’s best to do a real-life, practical programming exercise that’s fun, useful, and doesn’t bombard you with too many details or libraries — patterns, architecture, TDD, Maven, Spring, Docker, Scrum, etc.

That’s what this guide is all about.

What You Will Learn

Let’s not beat around the bush. After finishing this guide, you’ll be able to create a small Java application (from scratch), which will :

  • Be read in a directory of your hard drive and scan it for .mp3 files (learn core java skills/files access)
  • Analyze the files for their title, band, year, and metadata (learn how to use external Java libraries)
  • Save that metadata to a database (learn how to use JDBC)
  • And, then, finally open up a web browser (learn some more core java)
  • Lastly, display the saved data as an HTML page (learn about servlets)

Wooha! And, as images speak more than a thousand words, see the resulting program in action (and yes, there’s a couple of German songs in that gif )

Image title

But Wait, There’s More!

In this learning path, you will solve all the problems with simple, but modern Java tools.

In later parts, you will then build upon what you learned in this learning path and exchange certain parts of it with more complex tools. (Think TDD, Maven, Spring, Hibernate).

But fear not, for now, we will slow down, and everything will be dead simple!

And, if you want some more hand-holding and to have a closer look at how a professional programmer codes this exercise in real life, I have a screencast version of this guide here.

Project Setup

Prerequisites

To finish this learning path, you’ll need:

  • A good understanding of the basics of Java or any other programming language for that matter
  • Install a recent Java JDK (Versions 10, 9, 1.8, 1.7 will all do)
  • Install the free and fantastic IntelliJ Community Edition
  • You’ll need a directory on your hard disk with some .mp3 files — at least one.

That’s it!

Create a New Java Project

Sometimes, people get stuck when having to create a Java project from scratch. Should they choose their IDE to create that project? Or should they use Maven? Gradle? Clone some template online? You’ll use IntelliJ to create a blank Java project.

After starting up IntelliJ Community Edition, perform the following tasks:

1: 'Create New Project' > Select 'Java' > Choose your installed Java as 'Project SDK' > Next

2: Mark 'Create project from template' > Choose 'Command Line App' > Next

3: Give you project a name, any name you want and choose a project destination folder  > Finish


Voila — you have a blank project directory with an src folder to put your Java files inside!

In future installments of this guide, you’ll learn how to do this with Maven or Gradle and WHY you might want to do this.

Implementation

General Approach

I want you to create one Java class with one main method and put it inside the src folder of the project. You can also put it inside a package of your liking, like com.marcobehler.

And, contrary to a more advanced approach, I want you to put all the code you write inside that class, for now, even other classes.

While this won’t win prizes for the best design patterns or architecture, it will get stuff done. You’ll be able to improve the architecture and design in the future.

In the end, you should have come up with a file that looks like this:

public class Main {

    public static void main(String[] args) throws Exception {
    }
}


Now, it’s time to refer back to the bullet point list above and tackle each individual item, one-by-one. Feel free to take a break after each bullet point, step back, and continue the exercise the next day. Don’t worry, as long as you finish off the items sequentially, there won’t be a problem.

1. Validating User Input

First, think about how your program is going to be called by the end user. You are going to have something like this:

java -jar yourprogram.jar c:\mp3s


So, there’s going to be one argument to your program — that’s the directory that has your mp3 files. The arguments get passed into your main method, where you can easily access them:

    public static void main(String[] args) throws Exception {


To sum things up, you need to make sure that whoever uses your little jar file a) specifies that directory and b) that it is a valid, existing directory.

What’s more, Java has basically two file APIs. First, we have the "old" API from the very beginning of Java, which centers around the java.io.File class. Since Java 1.7, there’s also the new java.nio.Paths API, which offers some improvements.

I want you to use the Paths API to turn the String into a Path. And then, we need to check to see if the Path does, indeed, exist. If not, you throw an IllegalArgumentException with a sensible error message. And, if you are unsure about how to work with files in Java, you can always watch this series.

Give that a go now, run your program multiple times manually to check that your validations work, and only THEN check out the solution:

Solution

    public static void main(String[] args) throws Exception {

        // Step 1 : Check Program Input

        if (args.length != 1) {
            throw new IllegalArgumentException("You need to specify a valid mp3 directory");
        }

        String directory = args[0];
        Path mp3Directory = Paths.get(directory);

        if (!Files.exists(mp3Directory)) {
            throw new IllegalArgumentException("The specified directory does not exist : " + mp3Directory);
        }


2. Reading in Directories and Files

On to the next challenge, you need to read all the mp3 files of your specified directory, but you also need to ignore all the other file types. One way of doing that is through the way of globbing .

Read all the files, for now, and put them into a List — that’s it for this section already.

Solution

        // Step 2: Files

        List<Path> mp3Paths = new ArrayList<>();

        try (DirectoryStream<Path> paths = Files.newDirectoryStream(mp3Directory, "*.mp3")) {
            paths.forEach(p -> {
                System.out.println("Found : " + p.getFileName().toString());
                mp3Paths.add(p);
            });
        }


3. Parsing MP3 Metadata With an External Library

While you don’t want to reinvent the wheel when it comes to parsing mp3 metadata, you should perform a quick google search for something like:

"java mp3 library"


And, the first link that pops up is to the mpatric/mp3agic GitHub repository, which tells us that mp3agic can do pretty much anything we need to do, i.e. reading/writing metadata. So, we’ll give that a go.

Now, how do you add that library to your project? Java libraries come as simple .jar files. So, we could simply search for the mp3agic.jar file online, download it, and add it to the project. Problems occur when mp3agic, in turn, depends on other libraries (so-called transitive dependencies). Then, you have to make sure to download all these jar files into your project as well.

Hence, dependency management solutions, like Ivy, Maven or Gradle were born. But fear not, we are not going to focus on them today, instead, we are going the old-school way of using our IDE to do the right thing for us: IntelliJ lets you search for, download, and add dependencies to your project, using an online Maven mirror without using Maven itself. Isn’t it fancy?

So, inside IntelliJ, you want to do the following:

Select your project in the project view (left) > Hit F4 >
In the project structure dialog hit "Dependencies" -> +
Library -> From Maven
Enter "mp3agic" -> Hit Search -> Select the latest version


Or, you can have a look at this gif:

Image title

Good. The dependency should be added to your project. Now, it’s time to use it, and again, you can quickly double-check the Github repository for examples on how to use it, especially like opening an mp3 file and getting ID3v1 values sections.

Then, instead of saving everything into a List<Path> like in the previous challenge, I now want you to convert the Paths into Songs, a new domain class that you need to create as well, which looks like this:

    // Step 3: The Domain Class - Part 2
    public static class Song {

        private final String artist;
        private final String year;
        private final String album;
        private final String title;

        public Song(String artist, String year, String album, String title) {
            this.artist = artist;
            this.year = year;
            this.album = album;
            this.title = title;
        }

        public String getArtist() {
            return artist;
        }

        public String getYear() {
            return year;
        }

        public String getAlbum() {
            return album;
        }

        public String getTitle() {
            return title;
        }
    }


I want you to use streams for that, and to get a hook on the Java 8 Stream API, watch these videos for better understanding.

Once you are confident that your program compiles and runs, check out the solution:

Solution

        // Step 3: Files -> Domain Classes - Part 1

        List<Song> songs = mp3Paths.stream().map(path -> {
            try {
                Mp3File mp3file = new Mp3File(path);
                ID3v2 id3 = mp3file.getId3v2Tag();
                return new Song(id3.getArtist(), id3.getYear(), id3.getAlbum(), id3.getTitle());
            } catch (IOException | UnsupportedTagException | InvalidDataException e) {
                throw new IllegalStateException(e);
            }
        }).collect(Collectors.toList());


We've already come quite a far way, and in the next part of this guide, you will learn how to save the song metadata to the database, boot up a web server from inside your jar, and then take the whole thing for a final, working test run.

Stay tuned for our next installment on learning intermediate Java!

Connect any Java based application to your SaaS data.  Over 100+ Java-based data source connectors.

Topics:
java ,intermediate java ,practical programming ,patterns ,architechture ,metadata

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}