Where can I deploy my Java web app?

One of the very important topics in process of creating an application is distributing it to the end users. In most cases, a web application needs to be accessible, well, from the Web. That means that we want to have a place and an address where it will be available. Usually, we’d also like to have a separate test environment where we could test changes in a production-like environment, as „works on my machine” is not enough. With Matchlogger, I will have some very specific requirements for the environment providers:

  • The environment needs to be able to run a Spring Boot app, so it needs to support Java;
  • I use a MySQL database – there should be a way to provide one;
  • I will be using a custom domain name – I need to make sure I can connect a domain I already bought with my application;
  • I need to be able to add a certificate to support connecting through HTTPS;
  • It would be nice if I didn’t have to pay a lot for all that, so my maximum budget is for now about $10 per month. I don’t run a company for Matchlogger, so I expect small costs – at least at the beginning where it’s just an app I thought might be nice for me.

So, what options do we have? There are two main approaches we could use – we could either buy a service from one of the platform-as-a-service providers, like Heroku, Google App Engine or Openshift, or we could configure our own environment at one of the VPS providers. The first approach is easier for a developer (and saves you the hassle of making sure everything is up to date and configured correctly), but also has its restrictions and usually is more costly.

In case you happen to know any others that you’d recommend, feel free to leave a note.


For some time, it was the go-to platform for many developers. It feels like the hype has waned a bit, but it’s still one of the main developer-friendly platforms. One doesn’t have to worry too much about configuration specifics – you need to define a Procfile and git push it onto the remote.

  • Java support? Out of the box.
  • MySQL? Here it gets complicated.
    • You can use a ClearDB addon that adds a database as a service. In free tier, your database can have 5 MB of size and it allows 10 parallel connections. Paid plans start at $9.99 per month for a 1GB database with 15 connections. Not too amused.
    • Another option is to use the database you already have with your hosting account if you have one and you’re able to connect from outside. I did that before with Heroku, connecting to my linuxpl.com account. It worked, but I don’t have too much free space left there.
  • You can add a custom domain to Heroku both in free and paid plans. There’s a guide that describes the process.
  • SSL: With custom domains, apparently you need to use SSL endpoint addon. Price: $20 per month. Woah.
  • Cost: Well, it depends.
    • Free tier is limited to 1 node with 1 process. It can use 1000 hours of activity per month (the longest month has 744 hours – so you can run more than one app for some time). What is activity time? It’s when somebody’s using your app so it isn’t asleep. Heroku free containers start sleep mode after 30 minutes of inactivity. It means that first user that trips onto inactive application will experience delays as the app will start up. Of course, there are ways to circumvent that (say, have a task that will call your app every x minutes), but they might likely be breaking their Terms of Service. My colleagues were also complaining that free service is incredibly slow.
    • Hobby tier which might be more suitable for that app is $7 per dyno/month. There is a part saying that it contains free SSL and automated certificate management for custom domains, so if I understand it correctly, that might save the $20 per month payment.

In the case of Heroku-based setup for Matchlogger, we’re expecting payments between $7 and $37 per month. This is more than I expected, but let’s take a look at other options.


Another platform that is mentioned as a good one, especially among Java developers. It can also deploy an app by git push. Its new next-gen service is based on Docker images which might also be an asset. You can have up to three gears (likely their equivalent of Heroku’s dyno) for free and you pay for using more.

  • Java? Sure.
  • MySQL? Sure, a private database with full control. One important note is that each of the gears has only 1 GB of space, presumably for everything that’s related to the application. Additional gigabyte costs $1 per month.
  • Custom domain? In a bronze plan that’s hours-based and (if I understand correctly) includes three free gears.
  • SSL? As with custom domains.
  • Cost: In a bronze plan that would be more than enough for my purposes (I’d likely keep myself within 3 free gears) I might be able to use free tier only. In case I need to buy one gear to work 24/7 and, say, 3 GB of space, the cost would be about $17 per month.

Looks like Red Hat’s offer for Openshift is way better than Heroku’s.

Google App Engine

One doesn’t have to introduce Google. They, too, offer their platform as a service.

  • Java is supported
  • MySQL is offered through Google Cloud SQL. Their estimate for 5GB of 24/7, 1-instance DB is $8.54 per month. With 1GB instead of 5GB the estimation is $7.84.
  • Custom domain and SSL seem to be free of charge.
  • Instance – looks like it might fit in the free tier. At least that’s what I figured out from their calculator.

In this case, the only cost that’s visible upfront might be related to their DB services. Doesn’t look bad, but one must take a better look at the calculated values. They also have their own datastore that they like to promote instead of their SQL services.

Amazon AWS

One of the most popular services for application hosting. Their free tier offers 750 hours of computing time each month for a year. That’s enough to host one instance for a year – no costs attached. Afterwards, they still have a lot of other free tiers that might be helpful.

  • Java support – there are tutorials on Amazon website on how to deploy Spring Boot app on EC2.
  • MySQL is offered via Amazon Relational Database Service. This is also included in the free tier, with 20 GB of space and 750h of DB instance time. After that period, 5 GB with db.t2.micro instance should still be free of charge – if I understand their calculator well.
  • Domain and SSL – while it looks like to be possible (but hard) without it, the best way would be to work with Amazon Route 53. That’s their managed cloud DNS service. With 1 zone, the likely cost is $0.50 per month. SSL can be provisioned by AWS Certificate Manager, apparently free of charge.
  • Instance costs – I will likely want a reserved (though small) instance for Matchlogger. Their t2.nano instance hosted in Germany with 0.5 GB of memory after free year would cost $40 per year if paid entirely upfront. t2.micro with 1GB of memory would be $77.

EC2 is basically a VPS – Virtual Private Server. I don’t have much experience with EC2 yet, but I’d expect that I’ll need to take care of all required upgrades. Deployment can be resolved with AWS CodeDeploy that’s free of charge if you’re deploying to EC2.

I must say that this offer looks really nice. With a small application like I expect Matchlogger to be, I might be able to fit in $4 per year and have a one-year period of free or almost free usage at the beginning.

Other VPS providers

With VPS, you get access to a virtual environment that shares a physical machine with others. You usually don’t experience that, though – the only limitation are the constraints that are imposed on the machine. You usually have SSH access and full freedom to install whatever you wish. With great power comes great responsibility, of course – if you don’t feel well with system administration, this might not be your piece of cake.

There are a lot of VPS providers out there. You can find sites that do VPS comparisons and find out the best deals. As the topic is vast, I will describe only three providers that I am considering for Matchlogger.


$5 per month for their basic instance. They are well established in the market and once recommended to me by one of the admins at my company. If you sign up from Docker Cloud link, you get $10 credit for free.


Very popular hosting provider, both for normal hosting accounts and VPS. Starts at 15 PLN per month. Slightly cheaper than DigitalOcean.


Hosted in Europe (Vilnius, Lithuania) and surprisingly cheap. 1,24 EUR per month if you pay annually. My colleague suggested it to me and I find the price to be the most catchy factor.

What to choose?

So, I’m still wondering. Looks like Amazon has a really nice ecosystem and one year of free tier, which is appealing. A simple VPS would be the cheapest solution, yet I have some doubts about the fragility of some of the ultra-cheap VPS providers.

What would you choose? Do you suggest any other platforms? Leave a comment!

Matchlogger: March summary and stats!

It is April already, so it’s time for some summary on my „Get Noticed” contest results so far. Did it go as I expected?


First of all, things go a little bit slower than expected. 8 commits to the repository in March isn’t a great result. By now I have a working login and an ability to add teams (which I still want to restrict so that users could propose teams and an admin needs to accept them). My immediate goals are adding matches and, of course, deployment. BTW, did I mention that I own matchlogger.com? 馃槈 I would like the application to be available to the end users as soon as possible to be able to iterate with further development.

In total, the project now has 837 lines of code:

  • Java – 14 classes, 437 LOC
  • XML – 3 configuration files, 177 LOC
  • HTML – 5 files, 158 LOC
  • .properties – 6 files, 43 LOC
  • CSS – 1 file, 7 LOC
  • .yml – 1 file, 7 LOC
  • JS – 1 file, 6 LOC
  • .md – 1 file, 2 LOC


I wrote 7 blog posts with tag DSP2017 in March. That’s around the planned amount. The most popular were:

  • Choose your Licence, Luke! – 41 views
  • Google OAuth2 login with Spring Boot – 37 views
  • Spring Boot: saving OAuth2 login data in DB using PrincipalExtractor – 11 views.

Those three were also the most popular posts on my blog during March. Looks like if the posts are focused on explaining one topic and have examples, they are the most popular. Likely this update post won’t be nearly as interesting as those three 馃槈

Extra stats

Time spent

In March, I spent 14 hours, 11 minutes and 10 seconds on Matchlogger development (data thanks to Toggl). Further 12 hours, 24 minutes and 56 seconds were spent on blogging – mostly for this contest. That means that in total, I spent around 51 minutes daily on the contest.

Code frequency

Looks like I tend to work in bursts. Those bursts are likely the days where I didn’t have any other plans, so I spent a lot of time on Matchlogger.


I’m not using full git flow, but branch my code and merge it to master through pull requests. It is enough for my project needs. As you can see, I usually have up to two branches open. You can also notice that there’s one case where a branch didn’t get merged – that was my modern approach to Vue.js development that turned out to freeze my IntelliJ on assets lookup even before I could exclude node_modules from scanning.


Nothing too unexpected here. On weekends I work throughout the day (I’m writing this post at 9 am), during the working week I tend to sit and code in the evening as during the day I’m at work.

Even if not everything goes as smooth as expected, I really like my pet project. I already learned new things and it can be satisfying at a time. 10/10, would participate again.

15 things you learn about Java for OCA exam

It is fairly controversial to take Oracle’s Java certificates. One of the very vocal opponents of them in the local Java scene is Wojciech Seliga, who claims that he noticed that people with certificates performed worse at job interviews at Spartez than those that don’t have them (around 4:15). Even with such claims, I decided that I want to pass OCJP this year as I thought that it might be a good idea to review my Java fundamentals knowledge and make sure I don’t miss anything. What surprised me a bit is that with Java 8, the certification process is different than a few years ago and now one needs to first pass an OCA exam. At first, I was a bit dismissive – come on, this is just an exam that shows you how to write for loops – but then I took an example exam and scored… 25%.

So I learned. One important thing to notice is that Oracle’s Java exams test if you can be a compiler – there are multiple cases where they aim to trick you into parsing something that won’t compile. One can be surprised how much caveats there might be and that’s where a good point is to read a good book that prepares for an exam. I read a book by Jeanne Boyarsky and Scott Selikoff and highly recommend that one. The benefit of those preparations is that I structured some of the core Java knowledge – some things I haven’t yet seen in practice (thanks to Flying Spaghetti Monster!) as they aren’t usually good code examples – but at least when I see it in some legacy project in future I won’t run away screaming. Some of them are just something that’s easy and quite obvious, yet it can surprise.

Examples below aim mostly for junior/wannabe developers, but they might be a good refresher also for a developer with some experience. You can see all examples in my Github repository.

1. Can we use a different args name in main() method?

Yes, we can! The name can be any valid Java identifier.

2. Will that code compile?

Yes. We can have only one public class in the file and the file is named just as the public class.

3. What will be the output?

The output is 1. Number variable will be first assigned 2, then 3, then 1. With 3 you can see a static block initialization.

4. That’s a legal number?

A nice, fancy way to write 1000000.000222. Usually used to separate by three numbers, like int result = 1_000_000. Underscores cannot be at the beginning, end and around dot sign.

5. What will that code print?

A trick one. We abuse the fact that assigning a variable returns the variable. The result will be Hello!. It would work that way only with boolean. I highly discourage you from doing that.

6. Which statements are valid?

Line 5 is fine. Same with line 6 – we assign a value to s1 and s2 is declared without a value. Line 7 does not compile – we cannot declare variables with two types in one statement – even if the type is actually the same. Line 8 is okay, it’s just two statements in one line. Line 9 – does not compile. We didn’t provide a type for i4. If we declared i4 somewhere above with a type, it would be fine.

7. Why doesn’t this compile?

Division of two shorts gives us an int that cannot be implicitly cast to short. We need to explicitly do the casting:

8. Does this compile?

Nope. The first line is an int because it’s outside short’s range. Second one lacks an L sign at the end and is too large to be an int. BTW, did you know that you can add plus signs before numbers? Not that it’s helpful, but you can 馃槈

9. What will that code return?

Well, it won’t return anything because it won’t compile! In Java 8, one cannot switch on long and boolean types. In Java 7, switch on String was added that also previously wasn’t possible.

10. What will be the output?

The output here is:


Note that we use a static code block for the output. The main trick is that we put default not as the last one (as you would expect) and we forgot to put a break; there.

11. What does this code output?


We use a label to break out of two for loops at once. Feels a bit like goto, but can be used only in certain cases.

12. Are these strings the same? What will be the output here?


In this case I’ll guide you to a good answer on string constant pool from StackOverflow. One more thing to notice is that this pool is an implementation of Flyweight design pattern.

13. Can we get a new dog? What will be the result of running this code?

Exception in thread "main" java.lang.UnsupportedOperationException
	at java.util.AbstractList.add(AbstractList.java:148)
	at java.util.AbstractList.add(AbstractList.java:108)
	at pl.mmkay.oca.Level13ListFromArray.main(Level13ListFromArray.java:12)

Arrays.asList creates an array-backed List implementation. In that one we cannot add or remove elements. We could only replace an element. That’s why we needed to create a new ArrayList to add a dog.

(That one is actually a real-life example, in a flat that I currently rent with my wife, we have a contract saying that we cannot have more than 2 pets at a time ;))

14. What will be the output here?


It’s good to know what Arrays.binarySearch return values are. If an element is found, it will return an element’s index. If not, it will return a negative number that is

 -1 * index - 1 

where index is what would be the index of this element if it was in the array.

Important thing here is that array must be sorted beforehand! If it’s not, the results might be quite surprising.

15. Which element will stay in the list?

The only one that will stay will be 1. There are two remove methods in List class:

remove(int index)
remove(Object o)

For the first removal, the best match was the one with index. The second one looked for the right object.

That’s all, folks!

Hope you liked the examples. Now you know a bit more on how to act like a compiler.