I'm starting a project and I thought I'd document parts of it as I go along. So this isn't a treatise on server side Java so much as a rebuttal by example.
See, I once worked for a company that asked me and two other developers to start building the next generation of their flagship product. They wanted web services with a browser-based user interface, and it fell to the three of us to decide on the technologic and architectural direction. I came to the meeting expecting to walk back out with a charter to build a set of SOAP services implemented using Java.
Fortunately, one of guys suggested I look into REST. That turned out to be a huge pivotal moment, and the services layer I produced was elegant and easy to consume. Thank goodness for that, because the other major decision that came out of those meetings was, in my humble but experienced opinion, a disaster.
These other two developers -- good friends and respected colleagues -- advocated using Embarcadero's Delphi (it's a Delphi shop) over switching to Java and using off-the-shelf technologies. For context, this discussion was about 8 years ago. Their argument? "Java is dead."
Because I was voted down, I had to use Delphi Pascal to roll my own REST services, cross-database persistence layer with data dictionary and SQL generation, and the tools and test suites for each. Keep in mind this was 8 years ago. The REST facility and JSON library in Delphi was utterly broken, so badly that no one was using them and Embarcadero didn't bother to bring them up during conferences, so I couldn't rely on those. It took quite a while and, when viewed from a company perspective, very expensive in terms of time and money. Don't get me wrong, I'm supremely proud of the product that we built, but that time could have been spent somewhere else.
Add to that the fact that Delphi developers are an increasingly rare breed, whereas, thanks to Java's huge (and still growing) market share, you can't walk down a busy sidewalk of a major city swinging your arms without hitting a Java programmer. They spent more on developers and couldn't ever get enough of them because of that fateful decision. (Just recently they began investing in inexperienced H1B employees fresh out of college and firing all of the people that had 10+ years of experience, a move which may very well end up sinking that company... but I digress...)
After developing the REST services and the business object framework, I kind of hit a wall. There weren't any other fun projects at the company. I was leery of relying on Delphi for anything anymore because *that* is a dying system, and frankly at my age I thought it best to try to move into management. To be fair, the company tried to throw me a bone, but there weren't any real management positions to speak of that were available, and eventually we parted ways. Which turned out great for me. I'm still doing what I love, and making a good living at it.
So this project is my way of showing that, yes, the development would have been faster, more functional, and would have supported more operating systems. I mean, hell, if you do it right you can run a JVM with J2EE containers on an Android cell phone or a Raspberry Pi. It scales easily, and moving it to a Linux instance on cloud services is trivial.
August 1st, 2016: Setup
After thrashing around a bit doing some research, I decided to go with a development environment that I'm not entirely experienced with but am comfortable in. On a Windows 10 laptop, I installed VMWare 12 (which those developers also said was a dead product... smh...) and created a Mint VM. I dropped in the latest Eclipse and Tomcat 9, and started up a project using JAX-RS for REST support and JPA as the persistence framework. Most of the startup headache came from getting Eclipse to debug in Tomcat. Which still isn't working... But it compiles the WAR file and drops it in the right location, and Tomcat picks it up, so there's that. Minus the setup, it took me about 30 minutes to create my first REST service persisting customer data.
To compare and contrast, it took 6 months to get the basic framework and tool chain for the Delphi REST services stabilized and capable of performing the same function.
November 27th, 2017: Framing
So things got busy, I had to put this aside, and over a year later, about two weeks ago, I finally picked this back up in earnest. And now I've got a JAX-RS application started that can read and write data REST-fully. I messed around with a couple of "plug and play" REST frameworks, only to find that they were over-simplified or just did REST wrong. And, really, they just exist to cut out a few steps but, given the difficulty in setting them up and getting them functioning, it seems like a false economy.
A large part of the time over the last two weeks was just spent getting my IDE set up. After a lot of trial, error, and Stackoverflow, I can now setup an environment using Eclipse, Tomcat, and MySQL in no time, create Dynamic Web Application project in Eclipse, convert it to a Maven project, add the JAX-RS facet, update the Maven pom.xml with the dependencies I need, and I'm off to the races. And I got the debugging thing worked out.
Total time required for environment set up: About 2 hours.
At this point I've built a small framework for resources, data access objects, an XML driven data dictionary, and beans that requires minimal code to add a new resource. My next step is to build a small utility to display the hundred-plus tables I've designed into my schema in a list, allow me to select the ones I want to support (all of them) and generate the initial code for them. And yes, that would be MUCH faster than going through the list one at a time building the code.
Total time required to design and implement database schema and code up a framework for basic XML-configured resources: About 2 weeks. As opposed to months re-inventing the wheel in Delphi back in 2009. And, since I'm using Tomcat, I can use Struts 2 to define some pretty slick server side functionality for the UI. All with the ability to deploy the application on any operating system that will support a J2EE container. Not only are the off-the-shelf possibilities endless, but if I need some help, finding a competent Java developer will be easy and quite probably cheaper than it is to find competent Delphi help.
I recently set out to hire a subcontractor for Delphi work, only to find that the only viable candidate that contacted me wanted more per hour than I was charging. Don't get me wrong, he's really good and probably worth it, but it was an eye opener and confirmed my position that the decision on choosing a software development technology should be based in part on industry support for that technology -- how easily can you hire resources knowledgeable in that technology.
December 7th, 2017: Resource Generation
After getting back from spending a week in Hawaii, and all the preparation beforehand that the trip required, I got back into this and immediately focused on a utility to generate resources. In my TGEdit utility, I completed, in about 4 hours, a utility that will read the schema for an existing table and generate the Java and data dictionary XML to support it. I then copy the generated files into the correct directories, recompile Silverboat, and run.
That's it. With a 4 hour investment, I'm now supporting 188 resources. Not bad. If I was really going to get fancy, I'd have created a data dictionary utility that could create/update the schema, especially since, before I'm done, I'll have to modify the data dictionary descriptions to set some of the flags that have nothing to do with the physical layer, but since I already have a schema in place this was the fastest path for this project.
Truth is, I have a highly sophisticated data dictionary utility already built into TGEdit, but I'm not using that for this project yet, because TGEdit expects all the DD configurations to be stored in a single library file. Which is great if you want to prevent someone from tinkering with your meta data, but it means more work, and I'm short-pathing this as much as possible.
December 17th, 2017: Framework completed and functional
Had to step away for a few days to get caught up on some stuff, but over the last couple of days I found a few hours to complete the framework. It now successfully implements a very simple, streamlined, near-RESTafarian REST interface with the just the verbs to support CRUD: POST, GET, PUT, and DELETE, respectively. For GET, it supports URL parameters "cols" to control the columns returned, "filters" to specify one or more filter criteria, "sorts" to control data order, and "start" and "maxrows" for pagination.
As I mentioned in my last entry, I had built a code generation utility to generate the resource classes. While debugging the interface, that utility ended up saving me hundreds of hours. To allow me to continue using that facility, should I ever need it, I'm plan to make a small change in the abstract resource class to allow me to implement business rules and validations as decorator classes, keeping them separate from the job of wiring URL segments to the abstract resource logic.
I also implemented a simple login mechanism. I'm going to skip implementing SSL/TLS for now (I'm not storing customer data or state secrets) and instead jump straight to modifying an existing application to use Silverboat to mirror some tables. That's going to take a little while. This application has been around for 15 years, and some of the third party components have been end-of-lifed or their companies have gone out of business, so I can't migrate the application to a modern development environment with a high amount of pain.
December 29th, 2017: Calendar reporting
Merry Christmas!! The break from programming was a welcome one. Now I'm back in the game and burning up the keyboard.
One of the reasons I started to attack this project with gusto was because I came up with a use for it. I wrote a simple point of sale system for salons a long time ago, and I had always intended to push some of the data up to a network server to make the appointment book accessible via browser. Well, I finally got around to it.
I wrote a configurable utility for pushing the data from the legacy POS database up to Silverboat using its REST interface. Then, while the data was being copied, I wrote an appointment resource and the HTML+Javascript for a calendar page and a login page. The "calendar" page just lists appointments right now, but I'll expand on that later.
Having some experience with Angular, I started to build the web side using Angular 2, and may I just say, it sucks. The learning curve for version 2 is even worse, and all the hoops you have to jump through make no sense at first. So I decided to just use plain old Javascript. I got the login page and calendar page built and functional in about a day. I'll probably want to put my Javascript into a framework at some point, but for now it was a good decision.
June 11th, 2018: Deployment
You might notice that it's been quite a while since I reported on this. Two things happened:
1. I got completely bogged down with several projects at once. I've been up to my eyeballs in alligators. That, and I attended NRF in New York City and SaaStr in San Francisco. NYC was COLD!! Holy moly... I used to live in Washington, but I'm out of practice at surviving arctic temperatures and short on warm clothing. San Francisco was beautiful, as always, but SaaStr was less about technology and more about learning to sell online software subscriptions. 97% marketing, 2% start-up discussions, 1% free alcohol and food. I did *not* get my money's worth on that one.
2. Also, I got stuck trying to get the Tomcat 9 server on my cloud instance set up to do SSL. The hold up wasn't even the cert. That's easy enough to get once you resign yourself to the fact that self-signed certs are now considered a Bad Thing. I went ahead and procured one, but the installation is anything but smooth, and Tomcat comes with so many options for configuring a connector that it's easy to get lost. I kept getting stuck and running out of time, and then I'd have to wait until the next time I could dig back into it. This all started back in March. I completely lost momentum for 3 months!!
Before all that, though, I got an application built that can go off at regular intervals and upload specific tables to the Silverboat REST service. So now all the pieces are in place, and it's time to deploy.
My beta customer has asked that I implement the ability to allow stylists and customers to create and manage their appointments. Given that the REST server is already in place, and that I've found several free calendar display components, this climb might not be too steep.
June 30th, 2021: REBOOT
Silverboat got far enough to *almost* be a sellable product, and then two things happened. First, I got involved in one too many projects and ran myself right into the ground. Pro tip: Part of being successful is not taking on too much. And I did. The second was that Oracle announced they were going to start charging pretty heavy royalties on commercial products and services that use Java.
And after many months of discussions with other developers and following companies whose intellectual property was heavily reliant on a language and set of toosl that would now cost them a fair percentage of their profits on a continuing basis, I made the decision to port everything over to a mix of Kotlin and Javascript, depending on the project type.
I do want to say that working with Java has been a delight. So easy to develop with and deploy, so many high quality libraries and frameworks, such a large and wicked smart community. And yes, it was SO MUCH easier to construct the backend services using Java than it was to hand roll it in Delphi or rely on the REST offerings from Embarcadero. I'm not throwing Java away completely, but new commercial offerings will not employ that language.
Silverboat will be mothballed as soon as Silverboat 2 is ready for deployment, and that version will be the first GA release.
Copyright (c)2016, 2021 Todd Grigsby, all rights reserved