Recently, I’ve started to learn Java, after over 20 years since I first learned it. As a, primarly, PHP developer it’s been an interesting experience. PHP is still easier for web projects. Here are some reflections on why.
Java is a very rich and sophisticated language with features such as multithreading, lambda expressions, pattern matching for switch statements, and sealed classes.
It’s been growing and developing since it was first released on May 23rd, 1995, and is used in all manner of projects, from small to large – to outer space.
However, the language has become quite a behemoth, known for its verbosity and complexity – especially for beginners to the language.
But, in recent years, a lot of effort has been invested in making Java easier and more productive.
This is excellent, as there is a lot to love about it (despite what I’ve said about it over the years).
For full transparency, I started learning it at university, back in 1997, when it was a much simpler language than it is today.
Sadly, I didn’t keep up with it, and went wherever a role or client took me (to PHP).
Not that that was entirely a bad thing.
I love working with PHP.
However, I should have continued learning Java along the way.
Well, that’s what I’ve told myself for years.
So, recently, I’ve been spending time getting back up to speed with Java, and have found it a very enjoyable and rewarding experience.
And in this post I’m going to start stepping through what I’ve learned in the hope that, if you’re in a similar position, that it can help you as well.
I’m structuring the advice around a series of key points.
If one or more don’t make sense or are not applicable to you, feel free to skip over them.
Otherwise, I’d love to get your feedback in the comments.
I don’t think this is a controversial thing to say, as it’s something that the language seems to dictate – at least for someone new to the language.
Why, specifically?
Managing application dependencies, i.e., Java’s classpath.
In my experience, PHP has a far simpler approach to where and how it manages dependencies.
What’s more, because of Composer, which has gone hand-in-hand with PHP for over a decade, managing dependencies is (all but) trivial.
The same can be said for Ruby, Python, Go, and Rust, because of their dependency managers.
With Java, I feel you need a good IDE, such as IntelliJ IDEA and a build tool such as Maven or Gradle.
Without them, while, yes, you could write a semi-sophisticated application, I think you’d struggle to compile and/or run it, because of having to manually manage the classpath.
There’s far more that build tools provide, but I want to keep the post as concise as possible, so I’m going to focus largely on this point.
Here’s a rather simplistic example to show what I mean
Let’s say that I wanted to build a small web application.
In PHP, I could be up and running in under five minutes.
I’d start off with a small script, such as the following, borrowed from the Slim documentation.
<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
require __DIR__ . '/vendor/autoload.php';
$app = AppFactory::create();
$app->get('/hello/{name}',
function (Request $request, Response $response, array $args)
{
$name = $args['name'];
$response->getBody()->write("Hello, $name");
return $response;
}
);
$app->run();
The application has one route, /hello
, that requires a single route argument (name
).
When the route is dispatched, the name argument is retrieved from the route and included in the response body.
Whether using a text editor or an IDE, the code is pretty trivial to write.
What’s more, you don’t need a special nor sophisticated directory structure either.
As for the app’s dependencies, it only has two:
- Slim: This is the core of the micro framework, one that really helps you quickly write simple yet powerful web applications and APIs.
- Slim PSR-7: This is a strict PSR-7 implementation. If you’re not familiar, PSR-7 is a set of common interfaces for representing HTTP messages as described in RFC 7230 and RFC 7231, and URIs for use with HTTP messages as described in RFC 3986.
To install them (in the vendor directory), and any dependencies that they require, I’d only need to run the following command:
composer require slim/slim slim/psr7
The command also generates Composer’s autoloader (autoload.php), also in the vendor directory.
This file contains a list of where to find all of the classes provided by the application’s external dependencies.
That’s it.
There’s nothing more required on my part.
You don’t even need to know anything about Composer’s configuration file syntax; though, the more you know, the more it helps.
I can’t say how much time this has saved me over the years.
Finally, I’d start the application with the following command:
That’s it.
The app’s ready to use.
So, opening http://localhost:8009/hello/matthew in your browser of choice, I’d see the following.
Sure, it’s not the most sophisticated web application, but it has a basic routing table, DI container, simplifies handling requests and responses, and can rapidly be built upon.
To be fair, the more sophisticated the application becomes, the more I’d suggest more sophisticated development environments such as PhpStorm or Visual Studio Code are required, or, at least could be beneficial.
But, you don’t need them to get started with.
And, honestly, you may never need them.
What’s more, you don’t need a sophisticated and powerful build tool either.
I don’t believe the same can be said of Java
Keep in mind, this is coming from the perspective of someone getting into the language.
So, perhaps my knowledge is lacking, here.
While coming up to speed with modern Java, I chose to use IntelliJ IDEA Community Edition.
It helped me in so many ways, such as its inspections letting me know about better ways to write code.
But, even with all that it provides, without a build tool such as Maven, I have no idea how to manage Java’s classpath, how to download dependencies, where they are stored, or how I’d make them available to my code.
Again, this is likely just newness to to the topic.
But, that’s the point.
For a beginner, it’s pretty overwhelming.
But, if I’m not mistaken, IntelliJ (and other IDEs) do a significant amount of work on your behalf for building the classpath string so that the code can find all of its dependencies – something I’d hate to have to do by hand.
To be honest, the classpath was one of my biggest bugbears when I was initially getting started with Java, all those years ago.
That tools such as Maven and Gradle exist, I feel, show that I am not alone in my thinking, and that it’s a complex topic requiring dedicated tooling.
That said, this isn’t me hating on Java.
Now that I’ve gotten a bit of familiarity with Maven, I really like it and find it to be a solid solution.
It, and others, can save you a lot of hassle building and deploying code, but there’s a lot to learn.
So, now, let’s see how to build the same, small, web app with Java.
I’ll use the Spark framework, as it’s the one that I’m most familiar with, and it is inspired by Sinatra, which inspired the PHP frameworks I use most.
This should be a fun, little, journey that shows how it can be more challenging to start out with Java than PHP, rather than telling.
First up, follow “Instructions for IntelliJ IDEA” in the Spark documentation, which step you through how to setup a basic Spark project using IntelliJ IDEA.
In essence, they do the following:
- Have IntelliJ create the project structure for you
- Add Spark as a dependency in Maven’s configuration file, pom.xml
Now, update src/main/java/«your package»/Main.java, with the following code:
package org.settermjd;
import static spark.Spark.*;
public class Main {
public static void main(String[] args) {
port(8009);
get("/hello/:name", (req, res) -> {
var name = req.params("name");
return "Hello " + name;
});
}
}
This is a slight revision to the code in the Spark documentation so that implements the same functionality as in the PHP example, and tells Spark to listen on the same port as before (8009).
Then, to compile and launch the application, either press Shift + F10 in IntelliJ IDEA, or the equivalent in your preferred IDE or text editor, if you’re using something else.
Now, open the application’s default route in your browser of choice such as by navigating to http://localhost:8009/hello/matthew, where you’ll see the following.
Both sets of code achieve the same result.
They’re both pretty comparable to each other.
So, from a code perspective, there’s not much between them.
However, when it comes to building them, it’s a whole other story.
With PHP, as I said earlier, you just need Composer and the PHP runtime.
This is whether you’re on your local development system or on any remote system.
To be fair, for remote deployment (or local deployment with Docker or another containerisation technology, such as Podman) you also need some systems administration skills to integrate the PHP runtime with your browser of choice.
With Java, I have no idea how to compile and run it outside of IntelliJ IDEA.
So, sure, it runs locally, but how do I deploy it?
I have no experience with Gradle.
So, I won’t attempt to offer anything in that regard.
I have a little bit of experience with Maven.
But, after reading through the documentation and searching through StackOverflow for over several hours, while I’ve gotten closer, I’ve still not gotten the code to run.
I would assume that you should be able to run maven to build a self-contained Jar file, one that has all of the required dependencies.
Then, whether locally or on a remote machine, with Java installed, you could run the Jar file.
However, nothing I’ve tried works, so far.
Yes, I can build the Jar file, but attempting to run it never works.
I tried adding the following to pom.xml, with the intention of building a self-contained Jar file.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>org.settermjd.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
However, when running the Jar file, the following error is encountered:
java -jar target/sparktest-1.0-SNAPSHOT.jar
Exception in thread "main" java.lang.NoClassDefFoundError: spark/Spark
at org.settermjd.Main.main(Main.java:7)
Caused by: java.lang.ClassNotFoundException: spark.Spark
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
... 1 more
Alternatively, I tried adding the following to pom.xml as instructed by this tutorial from Baeldung:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<archive>
<manifest>
<mainClass>org.settermjd.Main</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
However, that resulted in this, slightly different error:
no main manifest attribute, in target/sparktest-1.0-SNAPSHOT.jar
So, after much time attempting to do in Java, what takes a moment in PHP, I can only say that…
Then, you need to invest in learning them both.
What’s more, I’d suggest you’ll need a good friend, colleague, or mentor to be your guide.
Gladly, I know a couple of legends.
I don’t want to seem like a Java hater.
And, I suspect it’s clear that I’m far more familiar with PHP.
But, this post is one in a series about learning Java as a PHP developer.
So, frustrations with Java are to be expected.
Java isn’t an unwieldly beast, as you may have heard or thought.
It’s made great gains in recent years and is, as a language, a lot simpler to learn than I had anticipated.
However, without a good IDE, backed by a good build tool, even modestly simple web applications seem to be a non-starter.
I could just be looking in the wrong place, and I hope I am, but this initial hurdle is a tough one.
I hope that, after I get past it, it’s a lot simpler from there on in.
Join the discussion
comments powered by Disqus