7 ms·
An Opinionated Guide to Modern Java, Part 3: Web Development
- mark242 12y agoIt's funny. An "Introduction to Modern Java Web Development" sounds like a primer for the Play Framework, Scala, and Akka. Each of the examples looks like the starter documentation for Play, in that you've got your json manipulation, routing, connecting to a database, DI, actors, etc. Java devs-- you seriously owe it to yourself to spend the time investigating and ramping up onto Scala and Play. This is where the future of Java web app development is being driven from, by Typesafe and the Play / Spray /Akka open source developers. You do yourself a great disservice by sticking with Spring, Hibernate, JBoss, and the old standbys.
- UK-AL 12y agoI put my money on Spring, Hibernate, JBoss lasting longer than Scala, Akka etc. Those technologies have stayed on, while other trends have come and and go.
- tmarthal 12y agoActually, it is basically Pivotal versus TypeSafe, not just Spring versus Akka or anything like that. I put my money on TypeSafe. Pivotal still (05/2014) doesn't have Java8 support for some of it's frameworks (grails https://jira.grails.org/browse/GRAILS-11063 https://jira.grails.org/browse/GRAILS-11063 ). TypeSafe pre-released versions of Play that take full advantage of Java8 features. Given that if you need to run a Java 1.4.2 app on top of JBoss (or Glassfish!) then the types of technologies that these two companies are pushing are solving problems in a different domain. And arguably the PermGen change in Java8 would benefit Grails/Groovy the most.
- olavgg 12y agoGrails 2.4 will support Java8, and RC2 was released today!
- pjmlp 12y ago> You do yourself a great disservice by sticking with Spring, Hibernate, JBoss, and the old standbys. Given the amount of money you get with them, doing consulting in Germany, I think they will stay around for quite a while.
- robinhoode 12y agoI'm curious if this is comparable to Rails rates.
- pjmlp 12y agoYou can get into projects doing 60K € working for others, freelancing is higher.
- lgieron 12y agoFor UK market, check out jobserve.co.uk. From what I've seen there, the rates for a typical strong dev are about the same in the Java and the web scripting languages worlds (js/node, ruby). However, for rare and/or exceptional experience, pay in the Java world can skyrocket. Also, finance is hiring mostly Java/.net/c++ guys, and their rates are much higher than what everybody else is willing to pay.
- mwcampbell 12y agoThe article doesn't even recommend Spring, Hibernate, or JBoss; in fact, it specifically recommends against Hibernate. Instead, it recommends Dropwizard, JDBI, and Dagger among others.
- oblio 12y agoWell, he doesn't recommend any of Spring, Hibernate or JBoss, if you read the article. And I think his point was modern _Java_ development.
- jebblue 12y agoAgreed, Java, JDBC, HTML/CSS/JavaScript - this is my preferred stack, simple, linear, understandable, maintainable.
- danieldk 12y agoBeen there, done that. In the previous company I worked at, some new projects were done in Play. The result: frequent API changes in Play, bad Maven integration, illogical APIs from the Java perspective (an artefact of Play being written in Scala), little documentation, and I don't know how it is now, but back then it was very had to make a minimal REST application without pulling a lot of baggage in. We rewrote these applications using JAX-RS (RESTEasy) and they were much simpler, easier to maintain, without API breakage in new framework versions. It just a bunch of methods with annotations. XML and JSON serialization is automatic (via JAXB and Jackson). And you can use the same lightweight ORM as Play (Ebean), since it's an external project. Well-thought out, mature technology is often better for getting work done than the hype of the day.
- bsaul 12y agoI've just started using play for the last two weeks, but so far i really don't understand the critics on java vs scala or the documentation. True, so far i've only dealt with json. / db / file upload & download , but even that covers quite a vast area, and it was pretty obvious that every time play had both a simple and documented way of doing those , even in java.
- Ironlink 12y agoI'd rather put my money on Spring learning lessons from Play / Scala / Akka. If they don't, the writing may indeed be on the wall.
- eropple 12y agoI don't feel like Spring can fix the core problems here, unfortunately--they're Java Problems, and Java Problems grow more and more acute as time goes on (though Java 8 is a good step in the right direction). The pleasant, compositional interaction borne of Scala's syntactical flexibility is why Play's wonderful to use (and Akka as the backend is largely behind-the-scenes). I used to be a detractor early in Play2 because of some large-scale-unfriendly decisions, but they've pretty much all been fixed.
- pron 12y agoAuthor here. As I explain in the article, I cannot recommend any framework that encourages asynchronous code. It's simply the wrong approach, no matter what functional tricks are used to make it more palatable. And the blocking Play APIs both feel foreign to Java, and provide no benefit over the standard, and widely implemented, JAX-RS.
- eropple 12y agoWould you mind substantiating why asynchronous code, successful in plenty of places and pretty much every new environment you're likely to run into, is so dogmatically the wrong approach?
- mark242 12y agoBlocking in Play should be foreign. On modern hardware architectures, writing code that blocks is the equivalent of throwing up your hands and saying "I can't trust myself to write efficient code so I'll just scale out my hardware and hope for the best". This is how Amazon winds up making so much money off Java developers who get constrained by thread pools and wind up spinning up a million instances of m3.medium machines. This is, imho, what makes Play so fantastic. That you can have def index = Action { hardComputation() } for blocking code, and change it to def index = Action.async { Future { hardComputation() } } and you have magically changed your application to be asynchronous through the request-as-actor paradigm of Play. Play makes it easy to write async code. Play makes it way easier to control configuration for things like thread pools, dispatchers, and the like vs. Jetty. The performance of the nonblocking async code is incredible, and winds up saving a ton of money and developer time.
- pron 12y agoYou should read the end of the post, then. The asynchronous, non-blocking approach, is always wrong. Regardless of your hardware architecture.
- kasey_junk 12y agoI know what you mean by the post and your current assertion that non-blocking is "always" wrong regardless of architecture, but I think there are a few caveats that you really need to apply here. You are talking about a problem domain where concurrency is what you are scaling and where the things that would block are orders of magnitude slower than processor time. If you were working in a problem domain where latency is what you are scaling and the blocking calls are on the same order as processor time, non-blocking approaches can be best as the blocking mechanism can still carry overhead even with light weight threads. Maximizing throughput is another beast entirely as well.
- deleted 12y ago[deleted]
- laureny 12y agoFor your point to stand, you'd have to spend some time explaining why you think Play is superior to DropWizard.
- krishy 12y ago> in that you've got your json manipulation, routing, connecting to a database, DI, actors, While I agree with you about the others 'json manipulation' is not an area that Play can even be compared to Jersey (Jackson). Jersey transparently converts the request body to the required input type whereas with Play you still have to un-marshal the body while taking care of errors (admiddently that can be 'hidden' away using Action composition but still is work that the developer has to worry about). With Jersey its magic that just works.
- zak_mc_kracken 12y agoFirst of all, your attitude is off putting and condescending. You don't convince people by telling them "You guys are living in the past, look how I do things, you should do the same". Please enough of that, especially coming from the Scala community. Let's act as professionals and judge tools on their merits instead of instigating flame wars. Second, I'm doing both (web Java at work, web Scala on my spare time) and in my experience, there is really no clear winner. What's especially interesting is that I can find about the same number of positive things to say about the Scala tool stack (Scala/Typesafe platform/Akka/Play) as I can say negative things about each of them. Every time I'm happy about something in the Scala world, I find something I'm not happy with that counter balances it (tooling, slowness of template recompilation, unprovedness of the actor model, Play's arguable step backward in the v2 compared to v1, etc...). Java is impossibly verbose and has a very limited type system compared to Scala but man... do I develop things quickly with it. There is close to zero friction to get from nothing to something workable, maintainable and fast. And the tooling is top notch, the environment and compilers are super stable, and Java 8 is numbing a lot of the pain I used to feel. In contrast, I feel that I'm often fighting against the Scala compiler whenever I write Scala code. It feels nice in the end to see how concise and neat the code looks compared to Java, but I'm never really convinced the pain was worth it. So, back to your original point: I've tried (and continue to experiment with) all these "new" technologies that Scala is claiming to bring to the table, and so far, I'm unconvinced that they are a clear improvement over what we currently use in the Java world. And given that Scala continues to be a marginal language on the JVM, I don't think I'm the only one doubting that Scala represents the future.
- jaxytee 12y agoI don't find mark242's comment off putting or condescending at all. He's just telling is like it is. Of course there are Java developers who can kick ass with Spring, Hibernate, Servlet containers, and war deployments, but all of these tools are huge, bloated, and starting to show their age. Modern frameworks like Play make things simpler for those of us who don't have +7 year JEE experience with Spring and Hibernate.
- cpprototypes 12y ago
- eranation 12y agoMy favorite - write Scala (or even Kotlin) with Spring (the new versions of Spring) or - Java EE 6/7 with non standardized Jersey MVC (hope they'll add it in Java EE 8) I think Play / Spray and Akka are great but let's differentiate between the language and the framework. You can write Play / Akka with Java (they added Java 8 support recently) and you can write Spring / Java EE with Scala (I do that all the time and it's working great) More than that, I have mixed Java / Scala projects and it works like a charm (once you configure maven / gradle correctly that is) The "new" Spring versions are nothing like it used to be. Also the new Java EE ones. no XML configuration files, all convention over configuration. And I sometimes prefer a @GET + @Path or @RequestMapping annotation over concatenating routes with ~ like they have in Spray. It's just a matter of preference and personal taste, but let's separate the language discussion with the framework / ecosystem discussion, they are not the same.
- vorg 12y ago> you can write Spring / Java EE with Scala It'd be nice if we could also write Gradle with Scala, or some other decent JVM language.
- ww520 12y agoI don't know. I loved Play Framework 1. Simple, lean, and lightning fast development. Play 2 came out and it looked strange, with various Scala things mixed in. It's a lot more complicate and bloated, and more buggy. The core piece is in Scala. The build is now sbt, yet another different thing to maintain. The template is Scala, slow to develop and slow to compile. The much-touted async feature is a meh. Most web apps don't have a high scalable requirement that async would help. If I really need high performance async support, I would go with Vert.x. Play 1 was almost perfect. Really hope someone would fork Play 1 and continue with it.
- metacity 12y agoPersonally I have become quite fond of Ninja Framework ( http://www.ninjaframework.org/ http://www.ninjaframework.org/ ); as simple as Play, but pure-Java (Java 8 too!). Even has a similar hot-reload mechanism as Play!
- jebblue 12y agoScala, Lisp, Haskell, Smalltalk do not register in my puny brain. C, C++, C# (which I don't EVER do any more), Java, those resonate and make sense to me. Bash and Python too for scripting.
- mushishi 12y agoNo, it isn't. I was a Scala enthusiast but experience has taught me to like Java and its maturity and dislike Scala's unstable complexity (maybe it's more stable now than back when I was onboard) but the language by design embraces abstraction building that is nice-looking superficially but deeply hard-to-understand when different features interplay, which also makes the tooling harder to get right. Also, Spring is not that bad, though sometimes I have hard time to understand some of the initialization/runtime problems. Hibernate and JBoss I rather skip, and use Tomcat and Dalesbred for relational data access.
- ninjazee124 12y agoBeen there, done that. I switched from Java to Scala and Play. Back to Java 8 and Spring MVC and couldn't be happier to be back.
- arielweisberg 12y agoI think that thread scheduling is really not the high pole in the tent for large numbers of threads. It's stacks. If you want to have a million stacks and each is allocated to the highest watermark that thread ever reached you will run out of memory. I suspect that task size has to be smaller than the typical bit of web processing code for context switching overhead to really dominate, or even be expensive enough to matter. That says as much about how expensive common tools and frameworks are as it does about the cost of context switching.
- rdtsc 12y agoThat is kind of the issue in Go at the moment. They have been oscillating between default stack sizes and also switched from green threads to real OS threads backing goroutines. EDIT: scratch the last statement about Go using OS threads for goroutines. I was thinking of something else. Sometimes on Linux systems, even allocating a large stack size doesn't actually consume that as physical memory. Malloc might give you the memory block, but until you actually make function calls or allocate data on the stack, it might not consume the memory.
- mwcampbell 12y agoWhen did Go switch from green threads to real OS threads backing goroutines, and why? Can you at least point to a mailing list post or version control commit?
- deleted 12y ago[deleted]
- rdtsc 12y agoSorry apparently that is not the case, I am an idiot, I was thinking of something else.
- jrochkind1 12y agoSomeone should really compile a list of all the non-toy languages/environments that started with green threads and switched to native threads, with explanations of what they were trying to do and what happened and why they switched. It seems to be a popular path. Before the next person thinks "oh, this would be so simpler and more problem-free if I use green threads", that person should really review the prior art, heh.
- java-lang 12y agoAs a modern java developer I was surprised to find no mention of Vert.X which to me seems like one of the most modern and forward-thinking java web frameworks. Not only does it support scaling your app out-of-the-box but also provides a simple way to deal with concurrency.
- oblio 12y agoIsn't Vert.X async a-la Node?
- java-lang 12y agoIt is asynchronous event driven like Node but can process events on multiple threads
- eip 12y agoI've been stuck using Vert.x for a year and half. I recommend using something else. It's a questionable framework mashed together with a poorly though out messaging system. I would rather use Spring Integration, Quasar, or Akka.
- java-lang 12y agoHmm, I find it surprising, hasn't been my experience at all.
- zmmmmm 12y agoWould be interested in any more concrete description of the problems? I'm considering using Vert.x in a project, mainly because of the polyglot features (ability to be extended by many different people some of who only know Python, others who only know Java and some who might only know Javascript, etc).
- eip 12y agoNon-standard build/deploy/run. Classloader per verticle type makes dependency injection painful. "I don't know what a Spring "ApplicationContext" is" -- Tim Fox Uses multiple classloaders so you can "run multiple versions of the same module at the same time". Not something I have ever done or would do. Uses Hazelcast for clustering but uses tons of classloaders so using anything other than simple types in Hazelcast is hard and inefficient. Message bus is tightly coupled to application cluster through Hazelcast. Messaging is missing the most useful features of AMQP like wildcard topics and queues. Only possible to do very basic message routing. Many messages have to be sent multiple times to mimic advanced routing. Dividing everything into 'verticles' encourages use of callbacks for everything. This increases code size and complexity which increases the need for testing. 'Callback hell' Encourages polyglot programming. Writing Vertx apps with Groovy makes me feel like I could add a whole chapter to 'How to Write Unmaintainable Code'. https://www.thc.org/root/phun/unmaintain.html https://www.thc.org/root/phun/unmaintain.html
- namelezz 12y agoThank you for sharing the amazing work. I do not know if there is a part 4 coming or not but do you have a good pattern for validating users' input?
- rdtsc 12y agoGreat work Ron.These should be a small (or maybe a full) book some day. Java is not my main language, but I liked the Advanced Topic: Blocking vs Non-blocking section and in general have been following Parallel Universe technology stack. If anyone is interested more in the async vs actors, there is a nice new podcast with Ron Pressler, Fred Hebert (Learn You Some Erlang For Great Good author), Kevin Hamond and Zachary Kessin http://mostlyerlang.com/2014/05/15/037-parellel-universe-with-ron-pressler/ http://mostlyerlang.com/2014/05/15/037-parellel-universe-wit... There is a discussion about concurrency, how Quasar works underneath (hint: there is an interesting bytecode transform that takes place during loading), shared state, Erlang, Clojure and Datomic. Anyway, highly recommend.
- zinxq 12y agoYou had me until you said Asynchronous I/O is faster than Synchronous I/O in Java. http://www.mailinator.com/tymaPaulMultithreaded.pdf http://www.mailinator.com/tymaPaulMultithreaded.pdf
- pron 12y agoThat's not what I said, or at least not what I meant. If you have blocking operations (that take a long time), then thread-blocking (as opposed to fiber-blocking or async) IO will require too many threads.
- zinxq 12y agoAgreed - for example a (canonical example) chat application (long lived connections, small amounts of data). But that's still not performance, that's then scalability? As in "how many active chat sessions could one server handle?". The opposite canonical example being a static, small-file web server. Short connections. How many files can you serve per second?
- cpprototypes 12y agoI've heard of Quasar before and had a general idea of what it is, but didn't look at the documentation carefully until now. My understanding is that I can run arbitrary synchronous code in Fibers? For example, consider the MongoDB client library: DBObject r = collection.find(query); It blocks while getting the results of the query. If I do something like this: for (int x=0; x < 100000; x++) { new Thread(() -> DBObject r = collection.find(query))).start(); } it's going to start 100,000 threads and freeze my computer. However, with Fibers I can do: for (int x=0; x < 100000; x++) { new Fiber(() -> DBObject r = collection.find(query))).start(); } and it will work fine since these are lightweight threads (like Go goroutines). I guess my main question is, can I use arbitrary unmodified synchronous code like this to run in Fibers or would the library have to be modified to support it? In this case, would someone have to update MongoDB library to add support for Fibers?
- eitany 12y ago
- haddr 12y agoI don't get the point of saying that application servers are dead and then... embedding application server within the application. If applications should be isolated they can be easily deployed on different application servers. The result will be the same, with the difference that we get all advantages of easy application deplyment using war files, and some nice tools supporting the whole process.
- jebblue 12y agoOne of the problems with application servers is like well, port separation, process isolation, when a change to the context is desired but it might affect all the apps you have to be very careful. Having your web app be its _own_ app is hugely advantageous.
- twic 12y agoYou can, and usually do, do exactly that with app servers. It's true that app servers were originally conceived as a way of hosting multiple apps in a single JVM, but it quickly became apparent that this was a terrible idea, and nobody does it. You run one instance of the app server per app. The app server is really just a great big bundle of useful libraries and a web framework.
- jshen 12y agoso why separate the two if there is always 1 app per app server?
- twic 12y ago(I'm guessing that was "So why separate ...", and you've just had root canal) They're separated in the sense that the app server is something you download that exposes an API, and the app is something you write on top of the API. It's much the same as the way the JVM and the class files are separated, or the way the OS and the JVM are separated. It's a fairly straightforward, pragmatic application of layering.
- zinxq 12y agoI will say though, dismissing Rob Von Behren in the area of async vs. sync IO with an anecdotal paragraph is a ballsy move. (i.e. "wrong approach")
- pron 12y agoI've been misunderstood. I have not commented at all about whether sync or async IO is better. I meant that if you have a long operation that blocks for a while, letting it consume a kernel thread is bad.
- jaxytee 12y ago>Let me put this clearly: asynchronous APIs are always more complicated than blocking APIs.. IMO I would rather use a single threaded server and manage synchronicity explicitly with callbacks, composable promises, comprehensions, monads, and "other functional shenanigans" vs having to sync shared state across threads and manage thread pools.
- phillmv 12y agoMan, am I ever fascinated with the complexity Java devs have to put up with. Maybe it's just been a long time since I had to deal with Java-land, but you need to know about so many different things just to get off the ground. Granted, this may be easier with newer frameworks, but still.
- kasey_junk 12y agoAs opposed to?
- phillmv 12y agoWell… checkout Flask, for instance: from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello World!' if __name__ == '__main__': app.run() Of course, you still need to know how Python Does Things, and The Thousand Ways To Deploy An App, and Package Management and so on, but for this trivial example it's a lot more conceptually lean than the semi-equivalent offered above. I don't need to know about `Bootstrap<Configuration>` or a `JModernConfiguration`. It's fair to point out that there will be a corresponding text file or option somewhere else, but…
- kasey_junk 12y agoimport static spark.Spark.*; public class HelloWorld { public static void main(String[] args) { get("/hello", (request, response) -> { return "Hello World!"; }); } }
- phillmv 12y agoLike I said above, "Granted, this may be easier with newer frameworks, but still." :). Good to see it's you can have some lighter loads. TFA mentioned this was how Modern Java Web Dev With Instrumentation is Done (worth mentioning that Javaland instrumentation is world class), so just going by the examples he provided.
- elchief 12y agoDo you really need to write a controller and all its actions for each resource with Jersey?
- elchief 12y agoI ask because with Spring Data REST, you don't
- logn 12y agoFor static resources you can load them like this: public class WebAppConfig extends ResourceConfig { private final String[] mimeTypes; public WebAppConfig() throws IOException { //load static resource from htdocs dir Collection<File> files = FileUtils.listFiles(new File("./htdocs"), null, true); ArrayList<String> mimeTypeList = new ArrayList<String>(); for (File file : files) { final byte[] contents = FileUtils.readFileToByteArray(file); Resource.Builder resourceBuilder = Resource.builder(); resourceBuilder.path(file.getAbsolutePath().split("/htdocs/")[1]); final ResourceMethod.Builder methodBuilder = resourceBuilder.addMethod("GET"); String mimeType = Files.probeContentType(Paths.get(file.toURI())); if (!mimeTypeList.contains(mimeType)) { mimeTypeList.add(mimeType); } methodBuilder.produces(mimeType) .handledBy(new Inflector<ContainerRequestContext, byte[]>() { @Override public byte[] apply(ContainerRequestContext req) { return contents; } }); registerResources(resourceBuilder.build()); } //load dynamic resources implementing interface Webpage register(MultiPartFeature.class); Reflections reflections = new Reflections(new ConfigurationBuilder() .setUrls(ClasspathHelper.forJavaClassPath()) .filterInputsBy(new FilterBuilder().include(FilterBuilder.prefix("com.example.mycompany")))); Set<Class<? extends Webpage>> webpageClasses = reflections.getSubTypesOf(Webpage.class); for (Class<? extends Webpage> webpageClass : webpageClasses) { registerResources(Resource.builder(webpageClass).build()); } mimeTypes = mimeTypeList.toArray(new String[0]); } public String[] mimeTypes() { return mimeTypes; } } ... public synchronized void start() throws Exception { WebAppConfig config = new WebAppConfig(); HttpServer httpServer = GrizzlyHttpServerFactory.createHttpServer(URL, config, false); CompressionConfig compressionConfig = httpServer.getListener("grizzly").getCompressionConfig(); compressionConfig.setCompressionMode(CompressionConfig.CompressionMode.ON); compressionConfig.setCompressionMinSize(1); compressionConfig.setCompressableMimeTypes(config.mimeTypes()); httpServer.start(); wait(); }
- rch 12y agoIs there a preferred way to submit typos other than in comments?
- dafnap 12y agoof course, email us at info@paralleluniverse.co - thanks!
- DCKing 12y agoIt's great to see how Java web development has progressed. I tried to make a Spring MVC web app work like a decent, modern, readable and productive web application two years ago and it just wasn't possible. Anyone interested in modern JVM web development I would still advise to invest time in learning Scala (or Clojure). They can work with your legacy code and libraries, but my productivity and general joy in programming shot through the roof when I started using Scala.
- thescrewdriver 12y ago> but my productivity and general joy in programming shot through the roof when I started using Scala. That was exactly my experience. Maintaining Java code from time to time makes me realise just how big the difference is.
- moondowner 12y agoYou can actually make a good Spring MVC-based webapp (with Thymeleaf, AngularJS and etc.); check out the JHipster Yeoman generator: https://jhipster.github.io/ https://jhipster.github.io/
- DCKing 12y agoMan, I wish that would have existed 2 years ago.
- BenefitOfDoubt 12y agoSounds like if you want to do serious web dev with Java in the real world, you really need a client front end templating library like Ember or Angular for most/all of the UI. So in essence, from a Java dev perspective, web programming is actually REST/JSON (service programming).
- runT1ME 12y agoHow does asynchronous futures end up being more complicated or in any way worse than the blocking threaded approach? for { user <- asyncGetUser(1) company <- asyncGeCompany(user.companyid) longresult <- asyncProcess(company.getSomething) } yield longresult
- saryant 12y agoHis issue seems to be the potential for modifying or referencing mutable state where in the yield block (or map or flatMap or whatever). It can be a problem. In Akka actors, referencing sender() from a future will be unpredictable because sender() could've changed in the mean time. I think there are three strong solutions which address this problem: 1) Immutable state. Solves this problem completely but accidental capture remains an issue. 2) Hiding mutable state within actors. I hesitate to present this as a general solution though since it really requires going all-in with actors (I don't consider that to be a bad thing, necessarily). 3) Projects like Scala Spores [1] aim to tackle this at the compiler by capturing mutable references and executing async closures in an immutable environment and prohibiting accidental capturing. IOW, turning accidental capture into a compiler error. I'm excited about this one. [1] https://speakerdeck.com/heathermiller/spores-distributable-functions-in-scala https://speakerdeck.com/heathermiller/spores-distributable-f...
- runT1ME 12y agoYou can (and should) use Futures independently of Akka actors. You're correct, hidden mutable state with Actors can be a problem, as with mutable state in general.
- saryant 12y agoAbsolutely, but people make mistakes. It's also somewhat unavoidable when you're dealing IO, unless you stick to .pipeTo(self)
- pron 12y agoYep, that's very nice code, except: user = getUser(1) company = getCompany(user.companyId) longresult = process(company.getSomething) is a) simpler (because that's what your normal code looks like), b) performs exactly the same (as fibers basically do the same thing, only transparently), and c) retains context (like ThreadLocal variables). So if that was the only way, I'd say, fine. But once you have lightweight threads, they are always preferred (even Scala now has its own poor-man's lightweight threads in the form of async/await).
- tristanperry 12y agoA very good article; well written and explained. For Java web development, it is worth re-considering Spring Boot though * (http://projects.spring.io/spring-boot/ http://projects.spring.io/spring-boot/) Spring MVC and Data (et al) powered entirely by annotations, and (e.g.) Thymeleaf for templating, can lead to some fairly powerful yet concise apps. We just started using this where I work, and it's a great step forward compared to old style, XML driven Spring MVC and Hibernate. Also Spring Boot does bring quite a lot of support for REST, via RestTemplate/RestOperations, along with support for consuming and producing JSON and/or XML at the controller levels. * Edit: I say re-considering since the article only briefly mentions it.
- smoyer 12y agoFull JavaEE development is pretty analogous - POJOs and annotations. I almost gave up on enterprise Java when every EJB required multiple classes, interfaces and often XML configuration too. Modern JavaEE isn't nearly as heavy as the article seems to think ... but I can't argue with the article's underlying pragmatism. Use the simplest set of tools that accomplish the task!
- hibikir 12y agoI am especially fond of his view on database layers. There's JDBC, which is extremely verbose and needs scaffolding to make it usable, and then ORMS, that will quickly fall apart the moment you actually need to do anything interesting with the database. The Spring solution to this problem was always my favorite part of their stack: JDBC template removed most of the error prone boilerplate from JDBC, adds a couple of features, and still lets you write SQL directly, which is probably what you should be doing in almost all the cases where a relational database becomes valuable. I can't wait for shops to start to use Java 8. The removal of so much boilerplate when trying to build functional interfaces should make the Java toolsets move forward very quickly.
- mahmud 12y agoAgain, just use jOOQ. It's beautiful executed design, written by smart people. http://www.jooq.org/ http://www.jooq.org/ I never cared for the library until I realized I'm spending a lot of time on the developer's blog; he is prolific and very knowledgeable about everything database and java. Was sold on it soon after.
- huherto 12y agoThat is precisely why I created this little project. It generates the boiler plate code to leverage jdbcTemplate and organize the data access objects. http://huherto.github.io/springyRecords/goals/ http://huherto.github.io/springyRecords/goals/ Also, this fellow HNer has been experimenting with Java 8 features. Pretty cool. https://github.com/benjiman/benjiql https://github.com/benjiman/benjiql
- boobsbr 12y agoI think myBatis does something similar, abstracts JDBC and lets you write SQL easily.