A story of me, my laziness, file uploads, and a lot of flex tapes.

in Programming & Dev2 years ago

It’s a story from a few weeks, or months ago.

I don’t really remember what I was doing during that time, but it’s likely that I’m just going through some code in my personal projects and doing things with them, poking around hoping to get some progress on a weekend. A friend of mine during that time was going through a course related to deep learning. He was trying his best to make the most amazing project possible for his presentation that is coming up soon, and he was mostly done with it. The model is working great, inputs and outputs are as expected, statistics of the model’s evaluation results are calculated, sample data for the presentation are prepared, and now all he needs is just a user interface to make his project look pleasing during the presentation.


It's the first image I got on Unsplash when I searched for "Java". I know, it's JavaScript in the photo, but hey it makes a nice header image. Photo by Tracy Adams on Unsplash.


User interfaces... ah, user interfaces.

He knew me as a “somewhat experienced” programmer, with quite a bit of wacky experience around multiple areas in the world of software developing. I don’t consider myself as a very good programmer (more like a big nerd that doesn’t properly focus on things that I should be focusing on), but he’s probably not wrong. Besides that, I do have a bit of knowledge on frontend development. He poked me on Discord, and we quickly sat down and discussed on his possible options and what he can do for it.

“Since your thing is written in Java... you can consider JavaFX? It’s not bad.”

“Maybe... but I come from Tkinter in Python, is there anything like that?”

“You reminded me of Swing, check that out?”

“Ouch, this makes my eyes bleed... next, next...”

In the end, we decided that he can use a webpage as a frontend instead. It solves quite a bit of problems – he doesn’t need to learn JavaFX or any other Java UI library, making a webpage is much less challenging, it shows that the project can be easily usable from anywhere as long as it has a web browser with JavaScript, and most importantly, webpages can be styled really easily. With a bit of CSS, he can implement some really flashy designs that grabs eyeballs with minimal effort. I also have a little bit of experience in web development, so I can hint him a little along the journey when he gets stuck. Having that decided, he proceeded with the idea, while I went and poked for ways to join this webpage with his application. I know that it's possible, but I'm not sure about the actual process. I'm also interested in knowing, so, let's start finding out!


A pretty nice looking webpage. Photo by Pankaj Patel on Unsplash.


Theoretically speaking, it is not a hard task to finish. We just need to implement a web server in his Java application that accepts file uploads, process it, and return the file. Or we only need to return the file path, and let the web browser load it. Sounds great! Now we just need to StackOverflow our way through this. It has to be easy, right?

Except that nope.

Apparently, file uploads aren’t that trivial. At least in this case of ours. I am not very comfortable working with Java, and hence I’m trying to not add (or copy paste, in this situation) too much code into the project. We are also trying to avoid including additional libraries into the project, because neither of us had any idea how this Gradle or Maven thingy works. The deadline is approaching, and frankly, I am lazy to spend another bunch of high intensity hours learning these new things just for something that we are probably never coming back to anymore after a few weeks. We then decided that it might be better if we can find alternative ways to achieve the same result, preferably with tools or languages that we already know. For example, Python.

The Python ecosystem is a pretty amusing one. The programming jokes of Python doing anything with a one-line import did not appear from thin air – it's indeed the case for a lot of complex tasks. Of course, it’s not likely for you to find something like is-eq-seven on pip, but you get what I mean. There are really a lot of good stuff in there.

(side note: wow, is-eq-seven uses 8 dependencies just to see if an object is equal to the number seven... I’m running out of vocabulary to express my feelings on this. Just, wow.)


Every time I look at dependencies I can't help but think of this. If you had been in programming for long enough to know the memes, this one should be familiar. (taken from imgflip.com)


Anyway, a quick search led us to something that we can use. Something that handles file uploads for us out of the box. Because it would be amazing to have a module that handles the popular task of file uploads out of the box, right? Of course it is.

We downloaded that module, fired it up, and poked around to see if we can really use it. Apparently, it accepts file uploads not only from its upload page (which we are not going to use), but from curl as well. This also means that we can just upload our file through a form in our page straight to this server without going through their default upload page. Amazing!

But, what should we do after uploading the file? We are trying to not edit the module, and we are also trying not to add too many new things into the Java application. Hence, here comes the wicked idea – we keep the partially working server code we previously taped onto the Java application, and edited it to receive not a file, but a string on the path of the file to process instead. The idea is that after we upload the file to the Python server, we send a request to the Java server, and the Java server processes the file, then return it to us.


image

How I think it would have went.


It sounds pretty great, because it keeps most of our previous and imported work intact (which I am, again, lazy to poke on), and we just need to add another request to our frontend code to finish the job. It indeed looks like a fantastic idea, so let’s get to it!

Then of course, we realised that things just don’t work that way. At least not directly.

Firstly, there’s the problem of us needing JavaScript’s XMLHttpRequest to be asynchronous. It is used to upload image files to the Python server, and these image files can be pretty big. If we don’t let them be asynchronous, the webpage will freeze until the upload is done, which is obviously, an experience worse than browsing with IE6. If we however let them be asynchronous, the second request to the Java server will be fired at the same time as the file uploading request, causing the Java application to crash because the file is definitely not ready for processing yet, or it probably does not even exist yet.

Luckily, it’s easy to fix. We just need to use some callbacks... wait, that doesn’t look really trivial, and you already know that I am refusing to spend too much time on something new for a project with a ticking deadline. Well, npm to the rescue! We found axios, which totally solves all of our needs. We didn’t even need to use npm, as we are using it in a browser. All it took is a simple one-line include and a three-line rewrite, and we solved this problem. Pretty quick!

But this happens to not be the only problem we need to solve. Apparently, even if both servers are running on localhost, the Java server is still considered to be on a different domain under Cross-Origin Resource Sharing (CORS), since it is running on a different port. Hence, it does not work out-of-the-box. To solve this, we need to... edit the Python server module, to add a Cross-Origin Resource Policy in the headers or something. A quick Google search that time did not reveal anything too easy or elegant to implement, so we’re back to the thinking board...


I don't use a whiteboard, but I've heard about how essential they are. Maybe I'll buy one some day. Photo by Kvalifik on Unsplash.


So, what would be the easiest thing to implement to let us achieve the desired result? At this point, it is clear that we must do something in one of these server’s code, but which would be the easiest?

Out of curiosity, I dug out the source code for the uploadserver module. It seems that, there are already handlers in the code that are used to handle access to different paths. It’s implemented with a bunch of if-else statements... which means, we can add our own handler directly into it by just adding our own condition into the pile? It is also super easy to send requests to from Python code, thanks to the requests library. So, how about, we point the second request from our webpage to this Python server instead, and let it send the request to the Java application on behalf of us, then finally returning the result to the webpage? Like a middleman. It won’t be too slow too when everything happens in localhost.


image

What I ended up making.


I quickly taped a demo on this up, tested it a little – it looks usable. I then zipped the whole demo thing up, sent it to my friend, and told him that we will figure out how to run this correctly on his PC later. When I finally got to explain how to correctly use this setup and how it works, it took him quite a while to understand what happened and why we are doing this... which, honestly, feels really spaghetti and stupidly complicated. He did implemented this into his final version of the project, though.

When I recalled the story today and wrote it out, it really seems like I could have done this at least 2 times faster if I just copy pasted the Java code I found at the beginning and just edit it a little more to make it do what I want. But... yes, I didn’t want to during that time. We are sometimes an emotionally driven species and I think that is one of those moments where reasons just fall apart and we just do what we feel is going to be nice.

But... hey, it works. He got a pretty good score from the presentation and project as well. Everything went pretty nicely, and we do think that we will never look at the code for another time. So, all is good. Maybe it’s also one of the moments where maintainability is not part of the spec, and we just did it.

Never again? I can’t promise. Heh. But if I shoot myself in the foot again, you'll see another post about it. It'll probably happen. You know, it's inevitable.


:)

Sort:  

This reflects the typical development cycle so well. Patching in elements until you get to the "it works" stage. Then it's just reiterate, refactor and replace until it becomes a really tight solution.

Although I still use XMLHttpRequest myself prolifically, on a new project perhaps consider Fetch. XMLHttpRequest is technically deprecated, although I doubt it'll ever disappear given the amount of code out there that still has it.

And Java... very tough to code, setup and debug, BUT... it has everything, memory light, runs like a banshee and scales to the heavens. My code runs over Tomcat (although front-ended with nginx as reverse proxy). Check that as even without a reverse proxy it would act as your "glue" to handle request/response to avoid running an additional language stack.

Totally geeking out with ya lol. Love your post!

Sometimes I also think that it is not terrible and is probably the usual practice to just flextape until it works, then try to improve upon it... but then there are just too many cases of me facing the decision of either that I just leave it there or I rewrite the whole thing from scratch. Perhaps I took that to the extreme...

I just tried to look for info on XMLHttpRequest getting deprecated, but apparently it's only the synchronous version of it getting dumped. The asynchronous version is still well supported it seems. I don't know if it will ever disappear, probably yes but after a very long time... when people finally invented something better than it. Like how IE finally (almost completely) disappeared after the years. But, I also don't know how to improve XMLHttpRequest, so... no clue. Lol.

Totally agree on how Java is a pain to setup. Luckily, we have IntelliJ IDEA, so it's no longer such a terrible nightmare. Jetbrains really knows how to make their stuff. I'm more of a C# person myself (with a special love towards TypeScript), but I still have to agree that Java is amazing. It's pretty intuitive, runs on a lot of places, and surprisingly runs really fast. Originally, we were also looking at Tomcat, but after 30 seconds of looking at it we were like "yeah not sure what's that, can we use Python?" :P so you know how this story actually started.

Thanks for dropping by!

IntelliJ IDEA - completely agree, Jetbrains makes amazing tools. I'm using Eclipse only because I started using it so long ago, but I wouldn't recommend Eclipse lol.

Patch it vs rewrite from scratch.. Do both! lol There are some routines here I've rewritten dozens of times to make it faster.. faster.. faster or more flexible. Even a complete re-architecture can open up possibilities, well, if time allows.

With your skills in C# and TypeScript you can pretty much do anything. Good tech to have!

It's funny how I begged customers to adopt IE over Netscape back in 90's. Then, it wasn't long before IE just meant I had to write a TON of extra css and javascript workarounds to support it. And IE became ridiculously slow compared to Firefox and Chrome's rendering engines, so ditching IE was easy.

I really enjoy reading about your programming tools and experience. Very nice of you to share.

Yes, if we have the time! Which I think is difficulty for large commercial codebases that happen to power multi-million businesses. It's a weird feeling knowing that the products that run the world are sometimes (or often... I don't know) questionable code. Well, at least for our small personal stuff it's always okay to chop off and remake a better one when we feel like to. If we aren't lazy. Lol.

I also think that with these two things I can do almost everything! Except that I'm still trying very hard to figure out the C# things beyond the basic things. The deeper I go the weirder the language looks with many other features popping out from nowhere. It'll take a long time before I get comfortable making big things with it :)

We should pray that Chrome will never accidentally wander into IE's path, it'll be the apocalypse. Or maybe we're already on the way to it (I think some people did say so). Hopefully not...

When I happen to get motivated enough to actually make stuff I'll try to write more about them! It feels pretty good to write about it and have people who understand it reading it.