URL mapping is a framework detail, not a language detail — although the framework can be limited by the language. In Sinatra you'd write:
get 'someroute' do
# do stuff
end
http://www.sinatrarb.com/intro.html#Routeseach style (these and half a dozen others) has its advantages and inconvenients. For instance, separate urls mapping (Rails, Django) give a starting point laying out the structure of the site and make views/controllers easier to reuse (as they're not coupled to URLs)[0], whereas annotating the handler directly gives a better view of where they're involved and how.
[0] They also make it simpler to "graft" sub-sites in
I don't mind both styles (after working with Spring MVC 3, Servlet 3, JAX-RS, and Rails)
@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. list_student_ids = get(STUDENTS.keys) # [0]
second example, Python: @delete
@path(r'{uid: [0-9]+}')
def delete_student(uid):
if STUDENTS.pop(uid, None): # [0]
return True
raise WebApplicationException(Response.Status.NOT_FOUND)
the last line generally wouldn't be this complex, in Flask you'd just call `flask.abort(404)` (which can be used inline with an `or`, as with waffle_ss's ruby example, but that's not usual/good Python style), in Django it'd be `raise Http404()`.Although in Django you'd really use the `get_object_or_404` shortcut for ORM objects:
def delete_student(uid):
get_object_or_404(StudentModel, pk=uid).delete()
return True
And you wouldn't bother with the return since a 200 result would mean the deletion was correctly executed.[0] Used Python's MutableMapping API here, it works slightly differently than Java's equivalent Map interface: `.keys()` returns a sequence of the mapping's keys and `.pop()` asks for a default value to return in case nothing was found there, otherwise it raises `KeyError` if the key was not found)
def delete_student(uid)
STUDENTS.remove(uid) || raise WebApplicationException.new(Response.Status.NOT_FOUND)
end get "/list_student_ids" do
STUDENTS.key_set
end
delete "/delete_student/:uid" do
STUDENTS.remove(params[:uid]) or raise WebApplicationException, Response::Status::NOT_FOUND
true
end
1. http://www.sinatrarb.com/I find it amazing that "DRY" has become such a positive pattern when it was touted as one of the driving points of the Ruby on Rails framework. Don't repeat yourself.
For instance, Java folks are always ready to throw exceptions instead of letting stuff resolve itself if it doesn't quite work.
-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.
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.
Jetty everything. You can even keep it for production.
I tend to use 'mvn tomcat:run' to run my dev server, which I find even easier, fwiw.
http://freemarker.sourceforge.net/
It's pretty simple and straigtforward, its what I use instead of JSP.
Also, if you're doing web stuff, I HIGHLY recommend sitemesh.
It's a really clean way of implementing layouts and everytime I use other languages like Python, I always try and find equivalents but am always disappointed.
The documentation is a bit thin, but the code is rock solid and very fast.
Combined with JEXL for an expression language, this is one of the best server side engines I've ever used.
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.
But you're absolutely right on most of these points.
All the formatting tricks are here: http://news.ycombinator.com/formatdoc
If JavaEE can reduce JPA2/Model boiler plate code, then it'll be much improved.
For distributed clustering, Hazelcast is amazingly good.
For massively scalable network services, Netty does a fantastic job.
That said, using a backtick character like that seems like a really error prone approach. Definitely not my cup of tea.
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>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
Is that like a 'full disclosure' notice or are we supposed to be terrified of your code?
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.
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.
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.
No, it's not.
http://iam.guillaume.bort.fr/post/558830013/why-there-is-no-...