Stéphane Epardaud, one of RESTEasy’s active users, is having a mini-conference/JUG in Nice, France on January 14th. One of the talks is on RESTEasy and JAX-RS. See his wiki for more details.
Mini-conference in Nice, France: RESTEasy/JAX-RS talk there
December 18, 2008
java, JAX-RS, RESTEasy Leave a comment
Web Apps vs. Web Sites
December 12, 2008
I’ve been excited for awhile now about going retro. Going retro to the days of 3-tiered GUI applications and substituting VB+DCE/CORBA+DB with AJAX+REST+DB. We got to talking about this quite extensively today in a Red Hat internal mailing list after the announcement of Red Hat’s participation in the Google GWT project.
One problem I had problems reconciling with was the search engine problem. If your web application is rendered dynamically through AJAX and GWT-controlled pages how will a search engine index your site? Michael Neale came to the rescue with:
If you want search engine crawling – then its not a web app, its a web site.
This statement is simple but profound. It makes sense because a web app is highly interactive, dynamic, and usally un-indexable. He’s on to something. He talks a little more in detail about it here. Thanks Mike!
Wrong Documentation in RESTEasy beta-9. Redownload please.
December 3, 2008
java, JAX-RS, jboss, REST Leave a comment
I accidentally bundled the old beta-7 documentation with the binary release of 1.0-beta-9. Please re-download to get updated documentation.
Apologies!
RESTEasy Beta 9 Released
December 1, 2008
java, JAX-RS, jboss, REST, Webservices 5 Comments
Follow documentation and download links from our main project page. View our full release notes from JIRA. Special thanks goes out to Solomon Duskis for helping me nail down the Spring integration and for implementing the Spring MVC bridge. This is a pretty extensive release with a lot of new features:
- Asynchronous HTTP (Comet) support via Tomcat 6, JBoss Web, or Servlet 3.0 (Jetty 7). This is a tiny, but simple abstraction over these APIs
- Expanded Multipart support. You can now marshal collections(Maps and Lists) of objects to and from multipart/mixed and multipart/form-data.
- Atom + JAXB support. I wrote a few JAXB annotated classes to represent the Atom format. You can embed JAXB classes within Atom content as well as marshall Atom to and from XML, JSON, and Fastinfoset.
- Atom support via Apache Abdera
- Arrays and Collections of JAXB objects marshalled automatically.
- Enhanced Spring support. We now support autoproxied beans as well as some nice Spring MVC support and the ability to output ModelAndView objects. Thanks Solomon!!!
This will hopefully be the last beta. I’ve been waiting patiently (since October 1st) for Red Hat and Sun to hammer out the licensing terms so I can download the JAX-RS TCK and get RESTEasy certified. I should be getting it any day now and so the next release of RESTEasy will be RC1 and certified. I’m not sure how long the TCK will take as I don’t have my hands on it yet, but I’m hoping around 6-8 weeks. Shortly after RC1 will be 1.0.
The Answer to the Alaskan Independence Movement
November 17, 2008
Thanks Sacha for sending this too me. Hey I would have been happy with just New England seceding!
Dear Red States:
We’ve decided we’re leaving. We intend to form our own country, and we’re
taking the other Blue States with us. In case you aren’t aware, that
includes California, Hawaii, Oregon, Washington, Minnesota, Wisconsin,
Michigan, Illinois and all the Northeast. We believe this split will be
beneficial to the nation, and especially to the people of the new country
of New California.To sum up briefly: You get Texas, Oklahoma and all the slave states. We
get stem cell research and the best beaches. We get the Statue of Liberty
. You get Dollywood. We get Intel and Microsoft. You get WorldCom. We get
Harvard. You get Ole’ Miss. We get 85 percent of America’s venture capital
and entrepreneurs. You get Alabama. We get two-thirds of the tax revenue,
you get to make the red states pay their fair share.Since our aggregate divorce rate is 22 percent lower than the Christian
Coalition’s, we get a bunch of happy families. Please be aware that Nuevo
California will be pro-choice and anti-war, and we’re going to want all
our citizens back from Iraq at once. If you need people to fight, ask your
evangelicals.With the Blue States in hand, we will have firm control of 80 percent of
the country’s fresh water, more than 90 percent of the pineapple and
lettuce, 92 percent of the nation’s fresh fruit, 95 percent of America’s
quality wines (you can serve French wines at state dinners), 90 percent of
all cheese, 90 percent of the high tech industry, most of the U.S.
low-sulfur coal, all living redwoods, sequoias and condors, all the Ivy
and Seven Sister schools plus Stanford, CalTech and MIT. With the Red
States, on the other hand, you will have to cope with 88 percent of all
obese Americans (and their projected health care costs), 92 percent of all
U.S. mosquitoes, nearly 100 percent of the tornadoes, 90 percent of the
hurricanes, 99 percent of all Southern Baptists, virtually 100 percent of
all televangelists, Rush Limbaugh, Bob Jones University, Clemson and the
University of Georgia. We get Hollywood and Yosemite, thank you.Additionally, 38 percent of those in the Red states believe Jonah was
actually swallowed by a whale, 62 percent believe life is sacred unless
we’re discussing the death penalty or gun laws, 44 percent say that
evolution is only a theory, 53 percent that Saddam was involved in 9/11
and 61 percent of you crazy bastards believe you are people with higher
morals then we lefties.Finally, we’re taking the good pot, too.
Peace out,
Blue States
Buggy/Broken Tomcat 6 Comet NIO APIs
November 12, 2008
I’ve had some bad experiences lately with the Tomcat 6 Comet APIs with the NIO Connector. I have a simple COMET servlet that spawns a thread and waits 5 seconds to respond to a Firefox browser. I also call event.setTimeout(10000) (timeout on the event of 10 seconds). After the response is finished writing I call event.close(); When using the Tomcat NIO, I don’t see a response until after event.setTimeout() time. So, if I set the timeout to 100 seconds I don’t see a response in the browser for 100 seconds.
Maybe I’m not adding some undocumented secret sauce, but when I test this out with JBoss Web and our APR connector, it works as expected: I see a response in the browser after 5 seconds. I also had a go with Servlet 3.0 through Jetty 7.0 pre3. Works as expected there as well.
This isn’t the only problems I’ve had. I also had a ClassCastException when I add a ServletFilter in front of a COMET Servlet. The APIs assume that all your filters implement CometFilter. Granted, I experienced this particular problem in the version of Tomcat 6 that ships with JBoss 4.2.3.GA, but after trying out the timeout problem described above with Tomcat 6 binaries from apache.org, I didn’t bother going any further to see if this was a JBoss specific problem or not. I did test to see if JBossWeb has the same problem…As expected it DID NOT.
So what’s the deal here?
- I’m just stupid?
- Nobody uses Tomcat 6 COMET + NIO APIs?
- Everybody who is doing asynchronous HTTP is using Jetty?
- Asynchronous HTTP is just hype generated by Greg Wilkins to breath new life into his increasingly irrelevant company?
My personal guess is that 2-3 are the main problems, with #1 a high possibility, with a sprinkle of 4. Anybody out there have any experiences with Tomcat 6 + COMET + NIO?
As a result of this, I’m not going to support COMET + Tomcat NIO with RESTEasy’s Async HTTP APIs. Only Jetty and JBossWeb.
JAX-RS Atom Support with Resteasy
November 10, 2008
java, JAX-RS, jboss, REST, Webservices 3 Comments
I have implemented Atom support which will be available with the next release of RESTEasy.
Although the Atom format is used primarily for the syndication of blogs and news, many are starting to use this format as the envelope for Web Services, for example, distributed notifications, job queues, or simply a nice format for sending or receiving data in bulk from a service.
RESTEasy has defined a simple object model in Java to represent Atom and uses JAXB to marshal and unmarshal it. The main classes are in the org.jboss.resteasy.plugins.providers.atom package and are Feed, Entry, Content, and Link. If you look at the source, you’d see that these are annotated with JAXB annotations. The distribution contains the javadocs for this project and are a must to learn the model. Here is a simple example of sending an atom feed using the Resteasy API.
import org.jboss.resteasy.plugins.providers.atom.Content;
import org.jboss.resteasy.plugins.providers.atom.Feed;
import org.jboss.resteasy.plugins.providers.atom.Link;
import org.jboss.resteasy.plugins.providers.atom.Person;
@Path("atom")
public class MyAtomService
{
@GET
@Path("feed")
@Produces("application/atom+xml")
public Feed getFeed()
{
Feed feed = new Feed();
feed.setId(new URI("http://example.com/42"));
feed.setTitle("My Feed");
feed.setUpdated(new Date());
Link link = new Link();
link.setHref(new URI("http://localhost"));
link.setRel("edit");
feed.getLinks().add(link);
feed.getAuthors().add(new Person("Bill Burke"));
Entry entry = new Entry();
entry.setTitle("Hello World");
Content content = new Content();
content.setType(MediaType.TEXT_HTML_TYPE);
content.setText("Nothing much");
feed.getEntries().add(content);
return feed;
}
}
Because Resteasy’s atom provider is JAXB based, you are not limited to sending atom objects using XML. You can automatically re-use all the other JAXB providers that Resteasy has like JSON and fastinfoset. All you have to do is have “atom+” in front of the main subtype. i.e. @Produces(“application/atom+json”) or @Consumes(“application/atom+fastinfoset”)
The org.jboss.resteasy.plugins.providers.atom.Content class allows you to unmarshal and marshal JAXB annotated objects that are the body of the content. Here’s an example of sending an Entry with a Customer object attached as the body of the entry’s content.
@XmlRootElement(namespace = "http://jboss.org/Customer")
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer
{
@XmlElement
private String name;
public Customer()
{
}
public Customer(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
}
@Path("atom")
public static class AtomServer
{
@GET
@Path("entry")
@Produces("application/atom+xml")
public Entry getEntry()
{
Entry entry = new Entry();
entry.setTitle("Hello World");
Content content = new Content();
content.setJAXBObject(new Customer("bill"));
entry.setContent(content);
return entry;
}
}
The Content.setJAXBObject() method is used to tell the content object you are sending back a Java JAXB object and want it marshalled appropriately. If you are using a different base format other than XML, i.e. “application/atom+json”, this attached JAXB object will be marshalled into that same format.
If you have an atom document as your input, you can also extract JAXB objects from Content using the Content.getJAXBObject(Class clazz) method. Here is an example of an input atom document and extracting a Customer object from the content.
@Path("atom")
public class AtomServer
{
@PUT
@Path("entry")
@Produces("application/atom+xml")
public void putCustomer(Entry entry)
{
Content content = entry.getContent();
Customer cust = content.getJAXBObject(Customer.class);
}
}
Double Check does work!
October 30, 2008
I was reading an interview with Josh Bloch about the 2nd edition of his great book Effective Java on Java.net yesterday and was pleasantly surprised to find out that if you use volatile within the Double Check pattern it is now safe in JDK 5 and above. I did not know this, the rumor mill was that Double Check did not work even in JDK 5. Here’s an example of Double Check. Josh suggests that you copy it as is and make no modifications.
// Double-check idiom for lazy initialization of instance fields.
private volatile FieldType field;
FieldType getField() {
FieldType result = field;
if (result == null) { // First check (no locking)
synchronized(this) {
result = field;
if (result == null) // Second check (with locking)
field = result = computeFieldValue();
}
}
return result;
}
Just this revelation alone makes me want to buy his book. I wonder what other goodies are in there. Seriously though, I’ve had need for the double-check pattern a lot over the years as avoiding synchronization can be the biggest scalability increase in writing middleware. I’m psyched that it actually works!
Idiocracy
October 29, 2008
There’s three things in this presidential campaign that really made me burst out laughing when I heard them. The first was when Vice Presidential candidate, Sarah Palin said “Its time that normal Joe Six-pack American is finally represented in the position of vice presidency.” Palin said if she and John McCain win, they will “put government back on the side of the people of Joe Six-pack like me.” Do you know what the definition of Joe Six Pack is? From the Urban Dictionary:
Average American moron, IQ 60, drinking beer, watching baseball and CNN, and believe everything his President says.
Beyond the fact that every time I hear Palin speak I think of the movie Fargo, why is this statement either appealing or reassuring to voters? I never understood why many Americans feel they have to vote for somebody they’d feel most comfortable having a beer with or somebody “just like them”.
The second hilarious thing was when McCain started talking about Joe the Plumber. “Joe I will fight for you.” I was cracking up every time McCain mentioned him in the debate. Here’s a man I actually switched parties in 2000 to vote for in the GOP primaries making a joke out of his campaign. He feels he’s so behind in the polls he has to pull this kind of publicity stunt? Sad, and actually quite hilarious at the same time.
The third and final belly burster is that “Joe the Plumber” is actually now campaigning for McCain in Ohio. Who the F is this guy? If you start reading about him you’ll find he actually isn’t really a licensed plumber and never completed the apprentice program for plumbing. IMO, McCain should fire the campaign advisor who suggested to make Joe the Plumber a celebrity. The guy is already stumbling and bumbling and making an ass out of himself and McCain.
All and all, this appealing to the lowest common denominator of society makes me want to secede from the Union too. Many times I think Mike Judge got it right.
JAX-RS Multipart support with RESTEasy
October 23, 2008
java, JAX-RS, jboss, REST, Webservices 7 Comments
I just finished implementing some “multipart/*” and multipart/form-data support within RESTEasy. It will be out with the next release. Highlights?
A JAX-RS compatable API
Our current support for multipart is through the MimeMultipart classes within the Java Mail library. They are limited because they do not use the MessageBodyReader/Writers available in JAX-RS. I have written two parallel APIs that provide multipart support in a JAX-RS way:
package org.jboss.resteasy.plugins.providers.multipart;
public interface MultipartInput {
List<InputPart> getParts();
String getPreamble();
}
public interface InputPart {
MultivaluedMap<String, String> getHeaders();
String getBodyAsString();
<T> T getBody(Class<T> type, Type genericType) throws IOException;
<T> T getBody(org.jboss.resteasy.util.GenericType<T> type) throws IOException;
MediaType getMediaType();
}
MultipartInput is a simple interface that allows you to get access to each part of the multipart message. Each part is represented by an InputPart interface. Each part has a set of headers associated with it. You can unmarshall the part by calling one of the getBody() methods. The Type genericType parameter can be null, but the Class type parameter must be set. Resteasy will find a MessageBodyReader based on the media type of the part as well as the type information you pass in. The following piece of code is unmarshalling parts which are XML into a JAXB annotated class called Customer.
@Path("/multipart")
public class MyService {
@PUT
@Consumes("multipart/mixed")
public void put(MultipartInput input)
{
List<Customer> customers = new ArrayList...;
for (InputPart part : input.getParts())
{
Customer cust = part.getBody(Customer.class, null);
customers.add(cust);
}
}
}
There’s a similar API for outputing multipart.
Multipart with vanilla Lists and Maps
Another feature I’ve added is the ability to use regular instances of java.util.List(any multipart format) or Map (form-data only) to represent multipart data. Its only usable when your parts are uniform though.
Here’s an example of using it:
parameter of the List type declaration. Here’s an example again of unmarshalling a list of customers.
@Path("/multipart")
public class MyService
{
@PUT
@Consumes("multipart/mixed")
public void put(List<Customer> customers)
{
...
}
}
That’s using input. The problem with output is that RESTEasy has no idea what mime type you want to marshal or List or Map into. So, the @PartType annotation is used. Here’s an example of outputing multipart/form-data with a map:
@Path("/multipart")
public class MyService
{
@GET
@Produces("multipart/form-data")
@PartType("application/xml")
public Map<String, Customer> get()
{
...
}
Multipart-Formdata with POJOs
Finally, I added the ability to map POJO form classes to multipart/form-data. You re-use @FormParam on fields and/or properties of a user-provided POJO. Here’s an example:
public class CustomerProblemForm {
@FormData("customer")
@PartType("application/xml")
private Customer customer;
@FormData("problem")
@PartType("text/plain")
private String problem;
public Customer getCustomer() { return customer; }
public void setCustomer(Customer cust) { this.customer = cust; }
public String getProblem() { return problem; }
public void setProblem(String problem) { this.problem = problem; }
}
After defining your POJO class you can then use it to represent multipart/form-data. Here’s an example of sending a CustomerProblemForm using the RESTEasy client framework
@Path("portal")
public interface CustomerPortal {
@Path("issues/{id}")
@Consumes("multipart/form-data")
@PUT
public void putProblem(@MultipartForm CustomerProblemForm,
@PathParam("id") int id);
}
{
CustomerPortal portal = ProxyFactory.create(CustomerPortal.class, "http://example.com");
CustomerProblemForm form = new CustomerProblemForm();
form.setCustomer(...);
form.setProblem(...);
portal.putProblem(form, 333);
}
You see that the @MultipartForm annotation was used to tell RESTEasy that the object has @FormParam and that it should be marshalled from that. You can also use the same object to receive multipart data. Here is an example of the server side counterpart of our customer portal.
@Path("portal")
public class CustomerPortalServer {
@Path("issues/{id})
@Consumes("multipart/form-data")
@PUT
public void putIssue(@MultipartForm CustoemrProblemForm,
@PathParm("id") int id) {
... write to database...
}
}
