

The Modern Java Ecosystem (for the Sinatra or web.py lover) - smanek
http://arantaday.com/the-modern-java-ecosystem

======
hello_moto
I'd like to add a few things here.

Jersey is an implementation of JAX-RS. It has 3 major pieces: jersey-core,
jersey-client, jersey-server. (The name should be obvious what they are for).

If you're writing JAX-RS services, you can return a few different formats:
XML, JSON, ATOM. All you need to do is to annotate the method with the
following annotation:

    
    
      // will return XML or JSON depending on the request from the client.
    
      @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) 
    

This is a big win if you need to support both.

    
    
      - Object to XML conversion is done by JAXB.
      - Object to JSON conversion is done by Jackson via JAXB.
    

Jersey is part of JavaEE 6 standard (part of your Application Server if it
supports it).

What's lacking from JavaEE 6 is an MVC framework which is targeted for JavaEE
7.

Another key feature is JAX-WS (the plain old SOAP WebService). The nice thing
about JavaEE 6 is that the minimum differences in the programming style
between JAX-RS and JAX-WS.

JAX-RS operates according to resources (e.g.: give me all students, give me
student with id=1, delete student with id=1, etc). So some of the examples
would be:

    
    
      // Rough pseudo-code, omitting a few JAX-RS annotation
    
      public class StudentResource{
    
      @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
    
      public <List> all(){}
    
      @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
    
      public Student get(long id){}
      }
    

JAX-WS operates according to services (e.g.: initiateInvoiceWorkflow,
performPayment, etc).

    
    
      public interface AccountingService{
    
        @WebMethod(operationName="initiateInvoiceWorkflow" ...)
    
        Invoice initiateInvoiceWorkFlow();
    
      }
    
      // have your implementation...
    

So in theory, you can have something that's called StudentRepository where you
can use that repository with both JAX-RS (REST) and JAX-WS (WebService)
implementation easily (I've done this and it's quite straightforward) if your
"Enterprise client" forces you to do so.

The important bit here is testing. You can easily test both JAX-RS and JAX-WS
implementation in both unit-test or integration-test. You can easily do unit-
test because you don't need to deploy them to the server: they're just normal
Java classes. You can do integration test by deploying them to the server and
generates the client implementation (in which I'll cover next).

The client-side implementation of JAX-RS is also similar to that of JAX-WS
programming style.

In JAX-WS, you grab a WSDL, throw it to a generator tool that comes with JDK
to generate the model (Invoice, Student, etc) and the proxy client-side to
call the server-side. Very very straightforward, 5 minute job.

In JAX-RS, you'd use jersey-client to perform HTTP call as follow:

    
    
      // url  => is a string that points to JAX-RS end-point e.g.: student/1
      // header => json? xml? atom?
      // type => (typeof Student) (well... it's Java).
      Student student = Client.create().resource(url).accept(header).get(type);
    

Keep in mind that in the client-side, your Student class must have roughly the
same structure and must be annotated using JAXB XML annotation (the client-
side also relies on JAXB -> Jackson -> Java object conversion for the case of
JSON, or just JAXB -> JAva object for the case of XML).

So no hacking using XPath or something like that (I work in Ruby once in a
while and when I read some of the 3rd-party libraries/gems that implement
client-side API against popular service provider, most of the implementations
do brute force using XPath querying node element and stuff).

PS: Excuse me for the poor formatting, where can I learn to format my comment?

UPDATE: fix the format.

Oh and one more thing: JAX-RS (Jersey) is just an implementation on top of
Servlet. So all of your previous knowledge regarding to Servlet (Context,
deployment, URL, Filter) will be definitely useful.

~~~
smanek
Thanks for the clarification and expansion! I was worried about dumping too
many details on people while trying to convince them that Java can be easy too
;-)

But you're absolutely right on most of these points.

All the formatting tricks are here: <http://news.ycombinator.com/formatdoc>

~~~
Omnipresent
Loved the original article and the expansion in this post made it even better.
Would you guys recommend any good books that cover JEE6 web services
thoroughly? I'm an experienced java guy but have not dealt much with web
services.

~~~
hello_moto
None. I usually rely on the source code + javadocs. I might be biased but I
find that most Java source code and documentations tend to be easier to read
due to common practices employed by newer projects.

I can only give you pointers to JavaEE 6 books (overall).

Beginning GF3 is an OK introduction to JavaEE 6:
[http://www.amazon.com/Beginning-GlassFish-Experts-Voice-
Tech...](http://www.amazon.com/Beginning-GlassFish-Experts-Voice-
Technology/dp/143022889X/ref=sr_1_2?ie=UTF8&qid=1322951777&sr=8-2)

Oracle Tutorial (formerly SUN tutorial) for JavaEE 6 is another OK one
(reviews were meh, but you've got limited choice so...)
<http://docs.oracle.com/javaee/6/tutorial/doc/>

I saw Amazon has the print edition and another one to be in stock by mid 2012
(Advanced Java EE 6...)

Here's another book covering Java EE6 (intro):

[http://www.amazon.com/Java-EE-GlassFish-Application-
Server/d...](http://www.amazon.com/Java-EE-GlassFish-Application-
Server/dp/1849510369/ref=sr_1_6?ie=UTF8&qid=1322951777&sr=8-6)

Seems to cover Servlet more than Apress book (first book).

You probably would need to know JPA 2.0 (ORM) as well.

And some more "best practices/real world-ish" tutorials:

[http://www.amazon.com/World-Night-Hacks-Dissecting-
Business/...](http://www.amazon.com/World-Night-Hacks-Dissecting-
Business/dp/1447672313/ref=pd_sim_b_4)

Good luck.

[http://www.amazon.com/Pro-JPA-Mastering-Persistence-
Technolo...](http://www.amazon.com/Pro-JPA-Mastering-Persistence-
Technology/dp/1430219564/ref=sr_1_1?s=books&ie=UTF8&qid=1322952208&sr=1-1)

------
scorchin
For those looking for something more like Sinatra in Java, check out webbit:
<https://github.com/joewalnes/webbit>

Here's an example of a simple Websocket chat server:
<https://gist.github.com/1421652>

_Disclaimer: It's an open source project that I have some commits to_

~~~
simpsond
Webbit looks much more like embedded Jetty and plain servlets than Sinatra. If
you really want something like Sinatra in you Java project, wire in Scala and
try Scalatra.

------
andrewl-hn
We use JAX-RS as a primary web framework in our current project and honestly I
can't get happier! We use Guava for low-level basic stuff and Google GSON for
JSON serialization. It seems to be on par with Jackson from ease-of-use point
of view:

MyType myVar = gson.fromJson(jsonString);

JPA on a back, some basic IoC in the middle (nothing fancy). Mockito and jUnit
for tests.

All in all it's just a bunch of small layered classes with some bits of
annotations and no xml. Well, one web.xml file with single servlet declaration
for JAX-RS :)

With good IDE (they all are great this days), Maven for dependencies, well-
known practices and modern APIs Java isn't that scary or cumbersome anymore.
It's just a nice small language. A bit verbose without closures and type
inference but still Ok.

I should note, though, that we generally use our Java layer as a service
provider. We keep main bits of logic on a client side in JavaScript and call
Java either for transactions and data, or in cases when something is hard to
do on a client. It's just easier that way.

~~~
hello_moto
Be careful with GSON. It by-passes your getter and setter.

That alone creates a bit of mismatch because JAXB (which is used by JAX-RS)
uses getter/setter by default unless you specified it otherwise.

And sometime you do have some logic in your getter/setter for validation or
other purposes.

I got bitten by this before while it seems like a small thing it's actually a
bit problematic.

If you're using JPA2, take a look at Spring-Data (formerly Hades). Spring-Data
helps you to reduce JPA boilerplate code.

The way Spring-Data works is by using a convention: specify your NamedQuery
and a Java interface with method name == NamedQuery name. Then magic suddenly
happens.

------
jshen
I'm not a big fan of the heavy use of annotations. When an annotation does
something other than what I expected it becomes a pain in the butt to figure
out why. Also, back in the day, jersey and guice didn't get along because
their use of annotations on the same methods conflicted because they both
wanted to drive the bus so to speak.

This has been resolved, but it left a bad taste in my mouth because there
isn't a good solution other than waiting for them to fix it.

~~~
latchkey
Annotations are a huge and important part of Java.

~~~
jshen
and I pointed out the headaches they caused me. I'm not really sure what point
you are trying to make.

~~~
latchkey
Conflicts in any piece of software are a pain in the butt. That is part of
software development though.

You say you aren't a big fan of 'heavy use of annotations' but you don't
qualify what 'heavy' is so I am guessing that it is pretty much all
annotations.

How do you make your determination of what annotations are 'ok' and what
annotations aren't? Or do you say something like 'oh, I won't use that
annotation because it might blow up on me at some later date'? What is your
mental process there? Is @GET good or is @POST bad? What about @Inject or
@JsonProperty?

The 'annotations leave a bad taste in my mouth' statement seems kind of odd to
me. Generally, a language feature isn't something that I'm careful about
avoiding. I could see making a statement like "I tried to use software product
XYZ and it was so full of bugs that I switched to software product ABC."

But annotations aren't a software product, they are a language feature that
products can take advantage of. It just happens to be that two products you
were using had conflicting annotations. No big deal, you still have choices as
you can just swap out products. That in itself doesn't make the functionality
that annotations provide taste bad.

I've met people who have had this view of annotations as being some magical
creature. They didn't understand them or how they worked at all. They stuck it
in their heads that 'annotations are bad', so we aren't going to use them and
aren't going to even bother learning how they might help us. Everything was
very black and white. I found this behavior really odd because everything in
software development is grey.

~~~
jshen
"You say you aren't a big fan of 'heavy use of annotations' but you don't
qualify what 'heavy' is so I am guessing that it is pretty much all
annotations."

The problem is that guice is using these annotations to wire things together,
but so was jax-rs. It's been over a year so I don't remember the exact problem
I was having, but the short version is that annotations don't compose well and
when two different frameworks require you to place annotations on the same
class/method, and then they conflict with one another, it because very hard to
fix.

This aligns with my feelings:
[http://www.nofluffjuststuff.com/blog/brian_gilstrap/2010/02/...](http://www.nofluffjuststuff.com/blog/brian_gilstrap/2010/02/java_annotations_have_become_pixie_dust)

~~~
latchkey
That is a great blog posting.

However, I don't know why the author would even suggest that annotations are
innocent looking. They aren't any more 'innocent' than an if statement.
Something like: 'if (myMethod())' could easily be a long running database
query or call out to a fibonacci solver. Should we all be afraid of using if
statements too?

I'm sorry, but there is really nothing 'magical' about annotations. It is
simply a marker on a class, property or method that other code can read from
and do things with. Prior to annotations, apps were processing Javadoc (@see
early versions of GWT), which was an even more terrible idea since you didn't
know if it was Javadoc or an annotation.

The summary is that a) software engineering is not easy and it does involve
knowing what you are doing in order for things to not appear 'magical'. b) If
you are going to put an annotation on something, then you should know what
code is going to read that annotation and what effects it might have. That
said, that isn't the fault of the annotation language feature.

~~~
jshen
My argument is that annotations don't compose well, interact in complex ways
that are hard to reason about and debug, and that this is worse than non
annotation based methods used in other languages.

Your response seems to be that one needs to understand the complex
interactions of annotations before using them, therefore annotations are fine.

That's a non sequitur.

~~~
latchkey
I disagree with your argument. To you, they are all of those things. To me,
they are great and none of those things. That is all I'm saying.

------
ww520
For web, Play Framework and Japid template are very good.

For distributed clustering, Hazelcast is amazingly good.

For massively scalable network services, Netty does a fantastic job.

~~~
latchkey
I'd never heard of Japid before. Thanks for pointing it out.

That said, using a backtick character like that seems like a really error
prone approach. Definitely not my cup of tea.

~~~
ww520
That's what I thought as well when I first saw the backtick, but after using
it for a while I found it to be perfect.

It's rarely used in any other context (besides Lisp). It's really unobtrude,
making the rest of the code standing out. It's at an easy to remember place at
the keyboard. The parser is good enough to catch any quote or backquote
mistakes. It's really an non-issue and you forget about it after a while.

A sample,

    
    
        <ul>
        `    for (a : list)
                 <li>$a  
        `
        </ul>

------
mattmiller
This is very cool. I am tied to Java b/c of Lucene and the Hadoop ecosystem as
well. Some more things I would like to see:

-Templating. Something like SimpleTemplate Engine in Bottlepy. <http://bottlepy.org/docs/dev/stpl.html>

-How do I get rid of Tomcat at least for development. I would like to run java -jar MyApp.jar -Dport=8080 and get a live running webapp in my dev environment.

~~~
benmccann
You can do "java -jar MyApp.jar -Dport=8080" with both Tomcat and Jetty using
what they call "embedded mode". I like the Jetty embedded mode much more
because it starts up so much faster. The Tomcat embedded mode does have the
benefit of an easier to understand API, but it's not worth the speed trade-off
for me.

Here's examples of both:

<http://www.benmccann.com/dev-blog/embedded-jetty/>

<http://www.benmccann.com/dev-blog/embedded-tomcat/>

I put together an example and uploaded it to GitHub. I'd love feedback on it:

<https://github.com/benmccann/sprightly>

P.S. Closure templates are cool because they can be used both client-side and
server-side. I'm not aware of other templating languages that have this
feature. I haven't used it much yet, but want to experiment with it more when
I get time.

~~~
swah
The list of technologies is really intimidating for outsiders. Its not like
"Oh, XYZ, thats just Django templating language". When I see Struts and
Hibernate, I know those things as gigantic opaque stuff that will take a long
time to learn...

------
icandoitbetter
>Javascript (which is basically just a Lisp with infix syntax ;-))

No, it's not.

~~~
roryokane
To elaborate, JavaScript doesn’t support macros, which allow arbitrarily
powerful semantic abstraction. And JavaScript does not have a regular syntax,
so even if it did have macros, you would have to special-case each type of
syntax (curly braces, statements, post-++ operators within lines) and handle
them specifically. First-class functions and closures do not a Lisp make.

------
rbanffy
In general, the code is still impressively verbose. OTOH, it's incredibly
short for Java code. I suspect that line/feature added count will increase
more quickly than it would with Python or Ruby and it will quickly become a
nightmare scenario indistinguishable from a more traditional Java web
approach.

~~~
smanek
How would these be any shorter in Python or Ruby?

    
    
      @GET
      public Collection<Integer> listStudentIds() {
        return STUDENTS.keySet();
      }
    

or

    
    
      @DELETE
      @Path("{uid: [0-9]+}")
      public boolean deleteStudent(@PathParam("uid") int uid) {
        final Student deletedStudent = STUDENTS.remove(uid);
    
        if (deletedStudent == null) {
          throw new WebApplicationException(Response.Status.NOT_FOUND);
        } else {
          return true;
        }
      }
    

I'll grant that Java programs often become more verbose than their Python/Ruby
counterparts - but I would argue that trait can be held to a minimum with the
proper libraries and coding style.

~~~
waffle_ss
In Ruby, everything evaluates to true except false and nil. Also, the last
statement executed is your return value. Therefore your first function could
be written as

    
    
      def delete_student(uid)
        STUDENTS.remove(uid) || raise WebApplicationException.new(Response.Status.NOT_FOUND)
      end

~~~
smanek
I love it!

And that is the reason I still write in Python or Lisp when I don't need
something (Hadoop, Lucene, etc) from the JVM ;-)

~~~
jblomo
If you need something from the JVM and want to write Lisp, use Clojure.
Checkout Hadoop extensions in Clojure at <https://github.com/jblomo/oddjob> .

------
zmmmmm
For me, the modern Java ecosystem is more about a sweet combination of groovy
at the edges with a minimalist Java core. it seems to be the best combo of
static and dynamic typing and capture a lot of the best of both worlds without
buying into too much religion or "enterprise" type complexity.

------
swah
But Play 2.0 is moving away from Java Servlets, IIRC... how do the modern
solutions compare in that regard?

~~~
mahmud
Play 1.x is NOT based on Java Servlets. No version of Play ever was, never
will be. From the BDFL himself:

[http://iam.guillaume.bort.fr/post/558830013/why-there-is-
no-...](http://iam.guillaume.bort.fr/post/558830013/why-there-is-no-servlets-
in-play)

