Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

As a Java developer, I thought this article had some interesting information about logging and monitoring. However, the deployment section had my scratching my head a little.

I've never totally understood why people want to make fat jars. It seems like a process full of headaches since you can't have jars in jars. Wouldn't it be much easier to create a regular zip file with a small script to set the classpath and and run the project?

I'm not sure I understand the motivation for embedded instead of standalone servlet container. The article linked to some slides but they mostly seemed be demonstrating that you can function using an embedded container rather than providing clear benefits. Maybe it would have made more sense with the associated talk.

Can anyone provide more insight to these?



Author here. A capsule is not necessarily a fat jar. It can point to Maven dependencies that are downloaded on the first launch, and can later be shared by other capsules. A zip with startup scripts is OK, but it requires installation.

As to full blown app servers vs embedded servers, I think it's the other way around. It's the big app servers that require justification, as they are a lot more cumbersome to set up and deploy.


It can point to Maven dependencies that are downloaded on the first launch

You wouldn't do this for a production deployment, right? Application starup that may or may not require access to the artifact repository to complete successfully. When that idea bounces around my developer neocortex, my sysadmin hindbrain starts reaching forward to strangle it.

And if you're not going to do it in production, doing it in development means having a gratuitous difference between development and production, which, again, is something i have learned to fear.

A zip with startup scripts is OK, but it requires installation.

'gradle installApp' works out of the box, and 'installs' the jars and scripts in your build directory, which is all you need to run locally. It's work of minutes to write an fpm [1] invocation that packages the output of installApp as an operating system package, which you can then send down the pipe towards production. This is simple, easy, standard, and fully integrated with a world of existing package management tools. Why would i use Capsule instead of doing this?

[1] https://github.com/jordansissel/fpm


Well, you can choose to embed the dependencies in the capsule, but I think the best approach for production deployment is have an organizational Maven repository (Artifactory/Nexus). This way you upload the libs, and the jars containing the actual apps to your repo, and all you need to do is restart the capsule (it can be configured to load and run the latest version).


So you're downloading jars from the repository to the production server when the app starts? I would feel very uneasy about that kind of coupling.

And i still don't see what advantage this has over just pushing out normal packages.


I feel uneasy about deploying the wrong version. With capsule, at launch it checks for a new version in the repo (if you configure it to use the newest version rather than a specific one). The packages are only downloaded once: not on every restart.

Alternatively, you can embed the dependencies, in which case it's just like a "normal package", only it doesn't require installation, and is just as easy to create (your build tool can create it). So it's a platform independent "normal package", with added features.


Interesting. I feel much more confident about deploying the right thing using an operating system package than some other mechanism. Almost everything else in the datacentre is deployed using operating system packages, so we get a lot of practice at deploying the right versions of things. The few legacy applications we have that are deployed via custom mechanisms are a headache - they require completely different tooling and troubleshooting knowledge to everything else.

But then, i have spent a fair amount of managing machines, shuffling packages around apt repositories, writing Puppet code and so on. Perhaps for a developer who has not served a sentence in operations, operating system packages are a less comforting proposition.

You seem to be very keen on avoiding "installation". Could you tell us about why that is?

And could you remind me what the added features of a capsule are? Putting aside the differences in delivery mechanism, which as i've said, i'm afraid i see as misfeatures, the only one i see is that it automatically finds the right JRE.

(Sorry you're being downvoted, by the way. I think this is an interesting discussion, and your gracious responses deserve upvotes, not downvotes.)


The advantage Capsule gives you is statelessness. The user does not need to put her system in a certain state. You get one file and you run it. It should work regardless of anything else that's installed -- or not -- on your machine, with the exception of an OS and a JRE.

There are other ways to achieve stateless deployment, and Capsule is not always the right fit. For example, it's not the right fit if your app requires an Oracle DB installed locally (it could be done, because Capsule supports an installation script embedded in the JAR, but that probably wouldn't be a good idea in this case). But when it is the right fit (e.g. microservices, grid workers etc.), it's much more lightweight than any other solution.


So your production application can potentially run in an untested configuration because someone has pushed a new version of XyzLib.

Again, for what advantage?

I mean, fine if you want to do that. But I wouldn't call it Modern Java or recommend anyone else do it.


How is that any more dangerous from deploying and installing an OS package? It's very hard to accidentally deploy to a release Maven repo. Maven Central makes you jump through hoops, and organizational repos have their own safeguards. They already deploy everything to their Maven repo anyway, why deploy again?

And if you don't want to enable automatic upgrades, you still get stateless, installation-free deployment.


That's the way we do it in production and it works great. Why create fat jar files and copy them to dozens of servers when you can just have each server pull down its dependencies from your repository.


So now the availability of your production service relies on the availability of your (development) repository. Another (pointless) point of failure.

And you can't see why this is a bad idea?


It should be obvious that if the repository were unavailable, we would not try to push a new version of our code. This is a much better approach since library dependencies are only usually downloaded once when we start a service for the first time, vs a fat jar that pushes dependencies every single time, leading to long startup times. This is a big deal when you've got a hundred servers and dozens of services on each.


It can point to Maven dependencies that are downloaded on the first launch

Please don't. Never assume that production machines have access to the internet or even an internal Maven repository. If they do, they're a security risk. There are plenty of scenarios I can think of where an attacker could possibly make your application download something from the internet, or has your application server functioning as an anonymous proxy by exploiting your application.


Looks like I should have read the Capsule Github page. I didn't realize Capsule was caching the project dependencies. I could certainly see that making projects much faster to deploy.

Aren't the app servers and the embedded servers the same servers just configured differently? Standalone it is configured with XML and and embedded it is configured with Java code. It doesn't seem to me like there is much of a set up difference.

As far as I can tell, it comes down who cares more about the settings for the server, the people who maintain the machines or the people who maintain the code. If those people are the same then it sounds like it really doesn't matter.


Multi-app servers usually take much longer to launch, deploying apps and upgrading the servers is a pain, and there's a host of other issues (like not being able to easily allocate resources to apps according to their needs).

> As far as I can tell, it comes down who cares more about the settings for the server

There's a lot of truth to that. I think that the whole devops approach is that they should be the same people. Of course, you might have valid reasons for not subscribing to that approach.


The difficulties you mention (aside from upgrading servers) is about the having multiple apps in a single server not standalone vs embedded. Although, if you are careful, it can actually be faster and easier to deploy to a multi-app server [0].

I grant you, upgrading servers can be more involved depending on how you do it.

[0] - http://tomcat.apache.org/tomcat-7.0-doc/deployer-howto.html#...


unzipping a folder and running a <10 line bash script requires installation? is that what you mean by installation?


Well, if it works for you then great. But doing that with every version (Capsule gives you automatic upgrades) might become annoying, and even dangerous, and if you can do the same thing with a single file that doesn't even require installation, why not make life even easier.


Ok, not disagreeing, just wondering what you meant by installation, Capsule sure looks cool.


Having moved from Tomcat to embedded Jetty, it avoids a bunch of problems - no two linux distributions can agree on where to put Tomcat particularly when you need multiple instances, and they have an unfortunate tendency to run out of PermGen space and need restarting after you've done a few redeploys. But it's mainly just faster, and much easier to use in development; you can just run the same java class either way, so running it with a debugger is easy, hot code replace just works, etc. As a bonus you can avoid having an XML config file. It's not a huge difference but it makes life slightly easier.

Fully agreed with the zip and script though, that's what we do (using the appassembler maven plugin, so it just happens as part of the build).


These arguments don't make sense to me.

I'm not sure why it matters that different distros put Tomcat in different locations. Embedding Jetty just means that now you have to restart every time. You could just do the same thing with standalone Tomcat instance. The only reason you are running out PermGen space on the redeploys is because your application is not cleaning up its threads on shutdown.

Why is it difficult to do any of those development things without having the server embedded in your application? Pretty much every Java build tool (Maven, SBT, Gradle, Lein) makes those things easy to do without specifying an XML file for your server. Also, they will frequently let you reload your application, which is faster.


> Embedding Jetty just means that now you have to restart every time. You could just do the same thing with standalone Tomcat instance.

So now either I need to figure out how to hook my deployment script into the host system's init scripts, or I need to package tomcat as part of my app (and worry about its shared library linkage). With embedded, my app is just a program, not at all integrated with the host system; it runs like a program and stops like a program.

> Why is it difficult to do any of those development things without having the server embedded in your application?

Because the tool needs support for the server and often it has to be done in a server-specific way. How does one use JProfiler on an app deployed in Tomcat? One edits one of the internal Tomcat xml files. How does one use JProfiler on an app that embeds Jetty? One runs it with the same command line arguments one uses for running any other app with JProfiler. And it's like that for every tool - the way to do it with Tomcat is slightly different, the way to do it with an embedded server is standard.

> Pretty much every Java build tool (Maven, SBT, Gradle, Lein) makes those things easy to do without specifying an XML file for your server.

If you're building a war you need a web.xml (or I'm seeing some speculation it can be done with annotations? Either way, much less clear than just making a servlet in code).

> Also, they will frequently let you reload your application, which is faster.

Not in a way that matters. If you're just doing day-to-day dev then IDE hot code replace is faster still. If you want to be sure you've cleaned out all traces of the old version and are definitely running your latest code then reload isn't reliable enough.


Why does standalone Tomcat need any more integration with the system than an app with embedded Tomcat? They are both Java applications.

Tool support is not server specific. In both cases you set the appropriate VM arguments. What XML file would you have to edit?

Yes, hot code replacement is faster (although it comes with other tradeoffs). Why can't you do that with standalone Tomcat? What is unreliable about reloading? You can leak PermGen space if you don't finalize your threads properly, but why wouldn't you be running the latest code?

You're right about the web.xml file. I had forgotten about that. I can see why you might prefer to write that in Java code rather than XML.


> Why does standalone Tomcat need any more integration with the system than an app with embedded Tomcat? They are both Java applications.

With an embedded Jetty my app can just be a jar or set of jars. Tomcat has a directory structure and ships as a binary rather than a jar so I'd need to unpack it and worry about it being linked correctly for the target system.

> Tool support is not server specific. In both cases you set the appropriate VM arguments. What XML file would you have to edit?

I forget the name - catalina.xml or something? You can't just run ./tomcat -agent:myagent.jar. because it won't pass the arguments through to the JVM, unless that's changed.


Tomcat is just a Java application. Its install is just a bunch of jar files with some shell scripts to simplify running them. If you look at an install you see that it is just running the Java class ' org.apache.catalina.startup.Bootstrap'. I'm not sure what linking you are worrying about.

For setting JVM arguments, I think you are thinking of 'setenv.sh' or 'setenv.bat'. These are shell scripts where you can set environment variables used when running Tomcat. This includes the standard 'JAVA_OPTS' to set VM arguments.


Actually, you can have Jars in Jars. Of course, you need to do the lifting yourself. It is actually very nice to have a simple unpack / installation application inside a Jar and to unpack the actual application from this Jar. In this way, the only requirement for unpack / installation is the JVM, which you already require to run the application itself. This is much more elegant than a platform dependent unpack / installation (installer binary or ZIP plus Windows Batch or a Shell script).



That is actually very similar to Capsule, except that it doesn't support Maven, automatic upgrades, and as far as I can tell - JVM configuration (heap size, agents etc). I think Capsule is a strict superset in terms of features.


Huh, jars within jars... sounds a lot like .war files!




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: