X

Recent Posts

REST

Jersey 2.x Client on Android - Take 2

In my earlier post i described what we did in Jersey version 2.16 in order to make Jersey client work on Android.The whole idea was that after separating JAXB providers out from the Jersey core module, things would just work out of the box.Unfortunately, it turned out the JAXB provider separation was not enough. Basic things worked (see my original post for a test case application), but Jersey was still trying to pull in some types not available in Android environment. Harish complained this caused his application to crash.In this post i would like to share a workaround, that should hopefully help overcome the above mentioned issue. The good thing is, you do not need to upgrade your Jersey dependency (version 2.16 and 2.17 should work just fine).The bad thing is the workaround relies on certain Jersey implementation internals, and i can not guarantee it would keep working for future Jersey versions.The workaround is quite simple and uses HK2 public API, that allows you to "unbind" components from the HK2 service locator on the fly. Here is the code:public static class AndroidFriendlyFeature implements Feature{ @Overridepublic boolean configure(FeatureContext context) { context.register(new AbstractBinder() { @Overrideprotected void configure() { addUnbindFilter(new Filter() { @Overridepublic boolean matches(Descriptor d) { String implClass = d.getImplementation();return implClass.startsWith("org.glassfish.jersey.message.internal.DataSource") || implClass.startsWith("org.glassfish.jersey.message.internal.RenderedImage");}});}});return true;}}The above feature must be registered with your Jersey client in the following way:client = ClientBuilder.newClient().register(AndroidFriendlyFeature.class);I have tested this only locally, so i am not sure the above workaround works for everybody, thus I would like to take this as an opportunity to ask for feedback. Please let me know if you had a chance to check this workaround outand whether it worked for you. It would help us to come up with a final solution for Android environment in Jersey.

In my earlier post i described what we did in Jersey version 2.16 in order to make Jersey client work on Android.The whole idea was that after separating JAXB providers out from the Jersey core...

REST

When to Use JAX-RS Class-path Scanning Mechanism

The short answer is: never!. I have seen several nasty (so called) "bugs" caused by this feature so that i felt like sharing this little advice via blog post:Never ever use JAX-RS class-path scanning feature in a production environmentClass-path scanning looks like a handy feature. Let say you do not want bother with enumerating all the components you would like to include in your JAX-RS application. Then your JAX-RS application class could look like:import javax.ws.rs.ApplicationPath;import javax.ws.rs.core.Application;@ApplicationPath("rest")public class EasyToConfigureJaxRsApplication extends Application {}The above example works great. When started, the application just scans the actual class-path, and adds every single JAX-RS component class found there to the actual runtime configuration. Isn't is great? Frankly, this kind of configuration could work just fine. Until someone changes either the system configuration (system class-path) or the way how you application is being packaged (a new 3rd party component could be added/removed from the application class-path then). These changes could be out of your control and if one of them happens, you application configuration could break. For this reason, it is not wise to use this kind of configuration in a production environment.One could think that for development purposes, using this cool feature would be fine. I think otherwise. You either develop an application targeted for production use, and then you want to stick with whatever will be used in production eventually (where class-path scanning is a no-go) or you just want to look around and play with things. In the latter case you still want to keep control and avoid any nasty surprise.To end up in a positive way. Here is another advise: Should you need to use any kind of scanning (for any reason), check out Jersey package scanning feature that allows you to control the scope of scanning. See the following links for some more details: https://jersey.java.net/apidocs/latest/jersey/org/glassfish/jersey/server/ResourceConfig.html#packages(java.lang.String...), https://jersey.java.net/apidocs/latest/jersey/org/glassfish/jersey/server/ServerProperties.html#PROVIDER_PACKAGES

The short answer is: never!. I have seen several nasty (so called) "bugs" caused by this feature so that i felt like sharing this little advice via blog post: Never ever use JAX-RS class-path scanning...

REST

Container Agnostic CDI Support In Jersey

Introduction At the time of this writing, Java SE support is being discussed as one of important additions to CDI 2.0 specification. Existing CDI implementations brought this feature already, only container bootstrapping has not yet been standardized. In Jersey version 2.15 we introduced Weld SE support, so that people could take advantage of CDI features also when running in Java SE environment. As part of this work, the old Jersey CDI module has been refactored so that it supports CDI integration in any CDI-enabled HTTP container.Containers Known to Work With Jersey CDI Support To stick with JAX-RS specification, Jersey has to support JAX-RS/CDI integration in Java EE environment. The two containers supporting JAX-RS/CDI integration out of the box are Oracle GlassFish and Oracle WebLogic application server. Apache Tomcat is another Servlet container that is known to work fine with Jersey CDI support. However, things do not work there out of the box. You need to enable CDI support in Tomcat e.g. using Weld. Jersey CDI example shows how a WAR application could be packaged (see tomcat-packaging profile in the pom file) in order to enable JAX-RS/CDI integration in Tomcat with Jersey using Weld. Another Servlet container that is supported by Weld is Jetty. Jersey CDI integration module should work there as well, but things have not been tested by Jersey team. If not bundled already with underlying Servlet container, the following Jersey module needs to be packaged with the application or otherwise included in the container class-path:<dependency> <groupId>org.glassfish.jersey.ext.cdi</groupId> <artifactId>jersey-cdi1x</artifactId> <version>2.16-SNAPSHOT</version></dependency>Request Scope Binding There is a common pattern for all above mentioned containers. Jersey CDI integration builds upon existing CDI/Servlet integration there. In other words, in all above cases, Jersey application must be deployed as a Servlet, where the underlying Servlet container has CDI integrated already and CDI container bootstrapped properly. The key feature in CDI/Servlet integration is proper request scope binding. If this feature was missing, you would not be able to use any request scoped CDI beans in your Jersey application. To make Jersey work with CDI in containers that do not have request scope binding resolved, some extra work is required. To allow smooth integration with Jersey request scope a new SPI, ExternalRequestScope, was introduced in Jersey version 2.15. An SPI implementation should be registered via the standard META-INF/services mechanism and needs to make sure CDI implentation request scope has been properly managed and request scoped data kept in the right context. For performance reasons, at most a single external request scope provider is allowed by Jersey runtime.Jersey Weld SE Support The extra work to align HTTP request with CDI request scope was already done by Jersey team for Weld 2.x implementation. In order to utilize Jersey/Weld request scope binding, you need to use the following module:<dependency> <groupId>org.glassfish.jersey.ext.cdi</groupId> <artifactId>jersey-weld2-se</artifactId> <version>2.16-SNAPSHOT</version></dependency> Then you could use your CDI backed JAX-RS components in a Jersey application running in Grizzly HTTP container bootstrapped as follows: Example Bootstrapping Jersey application with Weld support on Grizzly Weld weld = new Weld(); weld.initialize(); final HttpServer server = GrizzlyHttpServerFactory.createHttpServer(URI.create("http://localhost:8080/weld/"), jerseyResourceConfig); // ... server.shutdownNow(); weld.shutdown(); The above pattern could be applied also for other Jersey supported HTTP containers as long as you stick with CDI Weld 2.x implementation. You simply add the above mentioned jersey-weld2-se module into you class-path and bootstrap the Weld contatiner manually before starting the HTTP container.

Introduction At the time of this writing, Java SE support is being discussed as one of important additions to CDI 2.0 specification.Existing CDI implementations brought this feature already,...

REST

Jersey 2 Performance

During my sabbatical week in January i have done some performance improvements in Jersey server core module.These changes are already included in Jersey version 2.16.To make sure the changes indeed made a positive differencei have re-established continuous performance testing for Jersey server side processing.These automated tests allowed Michal Gajdoš to collect some numbers that show how performance evolved within Jersey 2.x version space.In this post i would like to share part of the outcome of this measurement.I hope to be able to reveal more numbers and details on the test setup in later posts.The above graph shows how Jersey throughput increased with increased Jersey version.Version 2.4 is emphasised here as till that version we had a serious bottleneck in Jersey, that avoided throughputto scale with increased number of worker threads.The above numbers capture increased throughput for regular resource methods handling plain text payload, where no sub-resource locatorsare involved. Sub-resource locators used to have poor throughput in Jersey versions prior to 2.16. In 2.16 Michal fixed thisand i would recommend you check out his post on this topic here.I think that the above graph clearly shows that we take performance seriously in Jersey.I hope that we will be able to further improve performance of Jersey in future versions.

During my sabbatical week in January i have done some performance improvements in Jersey server core module. These changes are already included in Jersey version 2.16. To make sure the changes indeed...

REST

Jersey 2.x Client on Android

From time to time, people are asking for Jersey Client support on Android device. Until Jersey version 2.15 it was not possible to get Jersey client running on Android devices due to javax.xml.stream dependencies included directly in the Jersey client core module. A list of Android supported Java packages is available here and the javax.xml.stream package is missing there.Current Jersey snapshot version introduces a new JAX-B module, so that all JAXB-B Jersey client dependencies could have been separated out. To prove things work better now for Jersey Client on Android, i have put together a simple mobile application to see what happens (project zip archive available for download).The BlockerTo reproduce the issue, i wrote a simple application consisting of just a single entry field for an URL, and then a big text viewwhere i display content retrieved from the given URL using Jersey Client 2.15. The application looks like this:I run the application in an Android emulator. Now after entering an URL and clicking the FETCH button here is what i got: Suppressed: java.lang.ClassNotFoundException: javax.xml.stream.XMLInputFactory at java.lang.Class.classForName(Native Method) at java.lang.BootClassLoader.findClass(ClassLoader.java:781) at java.lang.BootClassLoader.loadClass(ClassLoader.java:841) at java.lang.ClassLoader.loadClass(ClassLoader.java:504) ... 35 more Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack availableHere is a snapshot from the Android Studio:Not to mention, the mobile application crashed...The original issue has been removed, things work now, but...After upgrading Jersey dependency in my Android application to version 2.16-SNAPSHOT, i was able to retrieve some data via my Jersey Client finally:Great news, but when i checked the error log, i have seen this:[org.glassfish.jersey.message.internal.DataSourceProvider] with an exception: MultiException stack 1 of 4 java.lang.NoClassDefFoundError: javax.activation.DataSource at libcore.reflect.InternalNames.getClass(InternalNames.java:55) at java.lang.Class.getDexCacheType(Class.java:479) at java.lang.reflect.ArtMethod.getDexCacheType(ArtMethod.java:229) at java.lang.reflect.ArtMethod.getReturnType(ArtMethod.java:178) at java.lang.reflect.Method.getReturnType(Method.java:184) at java.lang.Class.getDeclaredMethods(Class.java:771) at org.glassfish.hk2.utilities.reflection.internal.ClassReflectionHelperImpl$3.run(ClassReflectionHelperImpl.java:119) at org.glassfish.hk2.utilities.reflection.internal.ClassReflectionHelperImpl$3.run(ClassReflectionHelperImpl.java:115) at java.security.AccessController.doPrivileged(AccessController.java:45) ...Hmm, another issue, not a real blocker (no application crash this time), but still quite annoying.What next?Apparently, we need to get rid of the other exception. Additionally, to make sure Jersey Client is usable on Android, i would like to have some more advanced scenario tested (JSON support e.g.) as well.Since this was my very first experience with Android development, any suggestions in this area are more than welcome. Otherwise i can only guess what kind of support people are expecting to have.SummaryFrom Jersey version 2.16, it should be possible to use Jersey Client on Android. The support is still not perfect, but i hope we will be able to resolve the last obstacles soon. Hopefully with some help from the community.

From time to time, people are asking for Jersey Client support on Android device. Until Jersey version 2.15 it was not possible to get Jersey client running on Android devices due to javax.xml.stream d...

REST

Jersey 1.10 is released

Yesterday, we have released the 1.10 version of Jersey, the open source, production quality, reference implementation of JAX-RS. The JAX-RS 1.1 specification is available at the JCP web site and also available in non-normative HTML here. For an overview of JAX-RS features read the Jersey user guide. To get started with Jersey read the getting started section of that guide. To understand more about what Jersey depends on read the dependencies section of that guide. See change log here. The major breaking change is we separated Servlet, EJB, and CDI functionalityout from the jersey-server module and put this Java EE related stuffto a new, jersey-servlet module. Then when deploying into a Servlet container, you will need to add one more dependency (on that jersey-servlet module).A similar change happened also to our jersey-grizzly2 module, whereif you need the Grizzly Servlet server, you will newly need an additional, jersey-grizzly2-servlet dependency.Another breaking change happened in the WADL area, where Pavel and Marek worked on improving and fixing bugs.Last but not least, Pedro Kowalski from the user community contributedstream support to the jersey-multipart module. For feedback send email to: users@jersey.java.net (archived here) or log bugs/features here.

Yesterday, we have released the 1.10 version of Jersey, the open source, production quality, reference implementation of JAX-RS. The JAX-RS 1.1 specificationis available at the JCP web site and also...

REST

Jersey 1.8 is released

On the last Friday, we have released the 1.8 version of Jersey, the open source, production quality, reference implementation of JAX-RS. The JAX-RS 1.1 specification is available at the JCP web site and also available in non-normative HTML here. For an overview of JAX-RS features read the Jersey user guide. To get started with Jersey read the getting started section of that guide. To understand more about what Jersey depends on read the dependencies section of that guide. See change log here. This, 1.8, version of Jersey is going to be integrated into GlassFish 3.1.1 and contains bug fixes mainly.The most important fix from this perspective is included in the JAX-RS/EJB integration layer. It is now possible to implement JAX-RS resources as EJB Session beans,which implement local and/or remote interfaces. This functionality was broken in previous releases.Another great addition should come into the client space, where Pavel has already done some preparationin the client API (including some breaking changes there) for the non-blocking asynchronous client feature. The implementation is already part of the experimental Jersey space and should be included as part of the stable Jersey bits in some of the coming releases.For feedback send email to: users@jersey.java.net (archived here) or log bugs/features here.

On the last Friday, we have released the 1.8 version of Jersey, the open source, production quality, reference implementation of JAX-RS. The JAX-RS 1.1 specificationis available at the JCP web site...

REST

Jersey 1.6 is released

On the last Friday, we have released the 1.6 version of Jersey, the open source, production quality, reference implementation of JAX-RS. The JAX-RS 1.1 specification is available at the JCP web site and also available in non-normative HTML here. For an overview of JAX-RS features read the Jersey user guide. To get started with Jersey read the getting started section of that guide. To understand more about what Jersey depends on read the dependencies section of that guide. See change log here. In this release, we started with the jersey-server modularization. Only recently, Grizzly version 2.0 was released. We moved the Grizzly 2 Jersey module from the experimental area, added the Grizzly HTTP Servlet support and some tests, and created a new Jersey jersey-grizzly2 module. At the same time we extracted the Grizzly version 1 support from the jersey-server module, and introduced a new, jersey-grizzly module. We also switched the majority of the Jersey functional tests from Grizzly 1 to Grizzly 2 to make sure everything works fine there. Grizzly 2 support was added to the Jersey test framework as well.Besides the Grizzly 2 integration, Pavel spent some cycles on the test code coverage report for Jersey.Another update in the Jersey 1.6 release is a great improvement of the Jersey OAuth client provided by Martin. To depict the functionality Martin also introduced a new, Jersey OAuth Twitter Client example.For feedback send email to: users@jersey.java.net (archived here) or log bugs/features here.

On the last Friday, we have released the 1.6 version of Jersey, the open source, production quality, reference implementation of JAX-RS. The JAX-RS 1.1 specificationis available at the JCP web site...

REST

Jersey 1.x Plans

It has been a long time i posted anything about the Jersey project here.As Paul has left Oracle, and i am taking over his leadership role for Jersey 1.x, i think it is the right time to start blogging again.This post should give you an overview of what are the plans for the Jersey 1.x in the near future.We want to improve Jersey integration with both GlassFish and WebLogic application servers,with focus on the following areas:Multiple Jersey versions running simultaneously within one containerEJB integrationMonitoringClient injectionAnother important thing we want to work on is non-blocking asynchronous web client, includingsupport for WebSocket and HttpStreaming. For the client generally, we want to look at the possibilities to get them automatically generated from WADL, which probablyincludes also some WADL related work on the server side (XSD inclusion).Besides the areas mentioned above, we will also be continuing on bug fixing and working with the communityon any other stuff. Jersey 1.x might still be a playground for emerging JAX-RS 2.0 features. Another, often underestimated thing, is the project infrastructure. We are willingto continue improving it. Pavel recently added Maven 3 support, and Jersey now builds faster.Last but not least, we would like to get back to the 6-8 week release cycle. The next, 1.6 version, release is planned for the end of this week.

It has been a long time i posted anything about the Jersey project here. As Paul has left Oracle, and i am taking over his leadership role for Jersey 1.x, i think it is the right time to start...

CZJUG

Jak se dostat do kanceláře SUNu v Praze na Chodově

Protože první poprázdninové setkání sdružení CZJUG proběhne vyjímečně v pražské kanceláři SUNu, zveřejňuji zde mapu, pár obrázků a stručný návod jak se na místo dostat.MapaKliknutím na mapu by se vám v prohlížeči měla otevřít aplikace mapy.cz, s nastavenou polohou místa setkání. Přesná adresa je: Praha 4, V Parku 8.Jak se dostat dovnitř, aneb proč být na místě opravdu včasPro snazší orientaci přikládám raději i fotografie. Na té první je pohled směrem ke kanceláři od stanice metra a autobusů Chodov. Na druhé je vidět vlastní vchod do budovy. Po vstupu do areálu se jedná o první takový vchod vpravo, hned za kadeřnictvím a dvěma obchody s jídlem, pitím a časopisy.Samotné setkání proběhne od 18h večer ve čtvrtém patře budovy, kam se musíte dostat přes celkem 2 recepce.Jedna recepce, provozovaná majitelem nemovitosti, je dole v přízemí. Tam vás pustí výtahem nahoru do 4. patra kde je ještě recepce firmy SUN. Prosím všechny účastníky setkání, aby byli na místě alespoň s desetiminutovým předstihem. Recepce SUNu totiž zavírá přesně v šest večer, a případným opozdilcům tak hrozí, že přijdou o poměrně velkou část první přednášky. Budu se sice snažit občas nakouknout ven, ale ten Gradle mě taky zajímá, takže nebudu na recepci pořád.Doprava MHDJe asi nejjednoduší možnost, jak se na Chodov dostat. Na místo jezdí linka metra C, případně autobusy č. 114, 122, 136 a 177. Jízdní řády lze snadno vyhledat na stránkách dopravního podniku, http://www.dpp.czPojedete autem?Vážně? I když akci sponzoruje společnost JetBrains kromě jiného chlazeným pivem? Co se dá dělat.Vzhledem k velké popularitě CZJUG setkání nejsem schopen garantovat parkování v garážích SUNu, takže tam prosím ani nejezděte. Máte ale možnost zaparkovat své auto v garážích obchodního centra Chodov, kde máte 3 hodiny parkování zdarma. Obchodní centrum je přímo na metru.Máte nějaké dotazy? Prosím napiště je do komentáře, ať odpovědi vidí všichni. Těším se příští středu nashledanou!

Protože první poprázdninové setkání sdružení CZJUG proběhne vyjímečně v pražské kanceláři SUNu, zveřejňuji zde mapu, pár obrázků a stručný návod jak se na místo dostat. Mapa Kliknutím na mapu by se vám...

CZJUG

Soutěž o SunSPOT development kit

Stručně řečeno je SunSPOT malé víceúčelové elektronické zařízení programovatelné v Javě.Disponuje celou řadou senzorů (teplota, intenzita osvětlení, akcelerometry), dále anologovými a číslicovými vstupně/výstupními porty, dvěma mikrospínači, USB portem a obvody pro radiovou komunikaci.Více podrobností o technologii SunSPOT lze nalézt v angličtině na stránkách http://www.sunspotworld.com/Na posledním setkání CZJUGu jsem technologii stručně představil, včetně dvou živých ukázek.Pokud budou ze setkání videa, dám link na ně do komentáře. Pokud máte zájem podívat se na nějaká videa už teď,můžete vyzkoušet třeba adresu http://www.youtube.com/watch?v=tv5ZaN9tSckFirma SUN Microsystems věnovala našemu sdružení CZJUG SunSPOT development kit, který obsahuje 3 výše popsaná zařízení, včetně DVD média se softwarem potřebným k jejich programování. A právě o tento kit jsme se rozhodli uspořádat pro členy sdružení soutěž.Pravidla soutěžePřihláškyDo soutěže se mohou přihlásit jednotliví členové sdružení CZJUG. Mohou tak učinit posláním e-mailu na mojí adresu (japod at sun dot com), a to nejpozději do konce tohoto měsíce, tj. července 2009. Přihlašovací e-mail by měl obsahovat plné jméno soutěžícího a jeho korespondenční adresu (fyzickou, ne e-mailovou). Počet soutěžících tímto omezujina 20, po dosažení tohoto počtu už nebudu další přihlášky akceptovat. Na setkání se mě několik lidí ptalo, zda mohoupracovat na řešení jako tým. Nemám s tím žádný problém, protože ani nedokážu poznat, kdo pracoval sám a kdo měl pomocníky.Chtěl bych jen zdůraznit, že přihlášky akceptuji pouze od jednotlivců, a vítězem bude pro mě z tohoto hlediska pouze jedenkonkrétní člověk (tj. je na něm, jak se o případnou výhru podělí se zbytkem týmu)Průběh soutěžeSoutěž bude dvoukolová. Z prvního kola postoupí do druhého pouze 3 řešitelé. Vítěz druhého kolabude vítězem celé soutěže, tj. vyhrává SunSPOT development kit.První koloCílem prvního kola bude vyrobit a zveřejnit prezentaci (může být i video, fantazii se meze nekladou)aplikace, která využívá technologii SunSPOT. Aplikace musí být omezena na použití zařízeníobsažených v SunSPOT development kitu (2 plnohodnotné SunSPOTy + 1 základnová stanice) a můžete použíti počítač.Všechny prezentace musejí být volně dostupné na webu do konce září 2009. Do té doby také musím obdržet adresukaždé prezentace na můj e-mail (japod at sun dot com).Výběr postupujících bude probíhat následovně. Každý z účastníků, který dodá řešení pro 1. kolo,bude mít možnost rozdělit celkem 6 bodů mezi jednotlivé prezentované aplikace (tj. včetně aplikace vlastní), a to takže třem různým řešením přidělí 3, resp. 2, resp. 1 bod. Po sečtení bodů postoupí do druhého kolasoutěžící s nejvyšším počtem dosažených bodů. Kde nerozhodnou body, rozhodne veřejné losování.Informaci o technologii přidělování bodů sdělím účastníkům na začátku října.Druhé koloCílem druhého kola bude danou aplikaci implementovat a výsledek opět veřejně prezentovat. Pro tyto účely půjčím soutěžícím SunSPOT development kit, aby mohli aplikaci odladit.Připomínám, že volně ke stažení je k dispozici emulátor SunSPOTu, který lze využítuž v průběhu prvního kola.Každopádně, kit mám jen jeden, takže se soutěžící budou muset ve druhém kole prostřídat. Podmínky střídánídomluvím s konkrétními soutěžícími, kteří se do druhého kola probojují.Termín pro dodání finální prezentace stanovím na základědomluvy. Předběžně počítám s půjčením kitu vždy na asi 2-3 týdny. Mým cílem je vyhlásit konečný výsledek soutěže do Vánoc 2009.Bodování výsledků druhého kola bude podobné jako v kole prvním. Bodovat budou mocivšichni účastníci soutěže (tedy všichni co dodali řešení pro 1. kolo), ale body už budou přidělovatpouze řešením 2. kola. Při nejednoznačném výsledku rozhodne opět los.Mezní situaceNapadají mě ještě různé mezní situace, které mohou nastat. Takže pro jistotu:V případě, že se přihlásí menší počet zájemců než 4, vynecháme první kolo soutěžePokud se přihlásí pouze jeden účastník, prodloužím termín pro přijetí přihlášek,případně soutěž zrušímDo soutěže se jeden člověk může přihlásit pouze jednou, tedy pouze s jednou aplikacíVyhrazuji si právo stanovit další pravidla pro situace které nejsou pokryté výše

Stručně řečeno je SunSPOT malé víceúčelové elektronické zařízení programovatelné v Javě.Disponuje celou řadou senzorů (teplota, intenzita osvětlení, akcelerometry), dále anologovými a číslicovými...

REST

Jersey 1.0.3 GlassFish V3 packages split up

Jersey version 1.0.3 is now available also to GlassFish V3 Prelude users via GFv3 update center. I am writing this, because several changes happenedabout how things work there.As you can see at the snapshot, the first big change relates to number of Jersey packages. Started from the 1.0.3 version, we are providing two separate packages.We are going to integrate with GlassFish V3 bits, so that people would not need to install Jersey separately. And as we wanted to lower the Jersey footprint in GlassFish V3, we have broken the original Jersey package down into two separate modules:Jersey CoreJersey Examples and DocumentationThe "Jersey Core" package contains OSGI modules for jersey-bundle, jettison, and jackson-asl libraries. This should be sufficient for you to deploy Jersey based web applications to GlassFish V3 Prelude without a need to bundle any Jersey related jars with your application WAR file and should be good for production."Jersey Examples and Documentation" package contains Jersey API javadocs and some examples. This package should be useful especially for developers, who want to learn Jersey, and see how it works before developing their own RESTful web applications. If you choose this package,the UC client will automatically install also the "Jersey core" module, and you will get installed everything you need to start up.A rather cosmetic change happened to location, where jersey subdirectory gets installed into. It has moved from $AS_HOME/jersey to $AS_HOME/glassfish/jersey.When upgrading from earlier versions of Jersey, you could be a bit confused with consequences of the above described changes. So if you upgraded into a newer Jersey version and try to figure out, where all Jersey examples and docs went, just install "Jersey Examples and Documentation" in addition and it should re-appear in $AS_HOME/glassfish/jersey.

Jersey version 1.0.3 is now available also to GlassFish V3 Prelude users via GFv3 update center. I am writing this, because several changes happened about how things work there. As you can see at the...

REST

Jersey aplication sharing Grizzly with static content and servlets

I was asked the question some time ago by one of my colleges here at SUN, and the same question was asked again recently at our user mailing list: "I want to run Jersey based application on Grizzly web server, but i want to also run another servlet from there, and possiblyalso serve some static content using the very same Grizzly sever instance. How do i do that?"The answer is as simple as follows. Having importedimport com.sun.grizzly.http.embed.GrizzlyWebServer;import com.sun.grizzly.http.servlet.ServletAdapter;import com.sun.jersey.spi.container.servlet.ServletContainer;You can just use: // static content is linked from here GrizzlyWebServer gws = new GrizzlyWebServer(8080, "/var/www"); // Jersey web resources ServletAdapter jerseyAdapter = new ServletAdapter(); jerseyAdapter.addInitParameter("com.sun.jersey.config.property.packages", "com.example"); jerseyAdapter.setContextPath("/jersey"); jerseyAdapter.setServletInstance(new ServletContainer()); // Another non-Jersey servlet ServletAdapter simpleServletAdapter = new ServletAdapter(); simpleServletAdapter.setContextPath("/simple"); simpleServletAdapter.setServletInstance(new SimpleServlet()); // register all above defined adapters gws.addGrizzlyAdapter(jerseyAdapter, new String[] {"/jersey"}); gws.addGrizzlyAdapter(simpleServletAdapter, new String[] {"/simple"}); // let Grizzly run gws.start();Your Jersey resource classes are placed in com.example package, and will become accessible at http://localhost:8080/jersey base.Your static content for http://localhost:8080/ is taken from /var/www directory and a SimpleServlet will become available at http://localhost:8080/simple.The only dependency you will need to include other than Jersey dependencies itself is <dependency> <groupId>com.sun.grizzly</groupId> <artifactId>grizzly-servlet-webserver</artifactId> <version>1.9.10</version> </dependency>If you are interested in some more advanced scenarios, you can get inspired at Jean-Francois Arcand's blog post

I was asked the question some time ago by one of my colleges here at SUN, and the same question was asked again recently at our user mailing list: "I want to run Jersey based application on Grizzly web...

CZJUG

Videa z únorového setkání CZJUGu

Videa z únorového setkání CZJUGu jsou k dispozici ke stažení.Jen pro připomenutí: jednalo se o monotematicky zaměřené setkání věnované technologii JavaFX.Úvodní prezentace Honzy Štěrby a Juraje Švece z pražského vývojovéhocentra společnosti SUN Microsystems byla přímo nabitá demonstracemipředvádějícími jednotlivé funkce JavaFX.Michal Škvor pak navázal předvedením nástrojů potřebných pro vývoj.Zajímavá byla ukázka podpory JavaFX v nástrojích firmy Adobe.Setkání bylo zakončeno poměrně dlouhou diskuzí, kde prezentátořinejen odpovídali na dotazy, ale předvedli další dema.Jednotlivé záznamy jsou přístupné na následujících adresách:http://mediacast.sun.com/users/jakub.podlesak/media/CZJUG2009.02-JavaFX-talk1/detailshttp://mediacast.sun.com/users/jakub.podlesak/media/CZJUG2009.02-JavaFX-talk2/detailshttp://mediacast.sun.com/users/jakub.podlesak/media/CZJUG2009.02-JavaFX-QA/detailsSlajdy jsou zde a zde. I když díky množství demonstrací platí, že kdo neviděl video, slajdy mu rozhodně stačit nebudou :-)Poznámka: Po downloadu by měla videa být přehratelná na Linuxu/Solarisu mplayerem (vyzkoušeno), z platformy Apple byste je měli být schopni přehrát přímo z webu. Na systémech Windows věřím, že po stažení QuickTime Playeru by přehrání mělo být také bez problémů.

Videa z únorového setkání CZJUGu jsou k dispozici ke stažení. Jen pro připomenutí: jednalo se o monotematicky zaměřené setkání věnované technologii JavaFX. Úvodní prezentace Honzy Štěrby a Juraje Švece...

CZJUG

Videa z lednového setkání CZJUGu

26. ledna 2009 proběhlo na půdě katedry počítačů, ČVUT FEL, setkání CZJUG na téma webové služby.Za firmu SUN Microsystems vystoupil Marek Potočiar. Jeho prezentace projektu Metro byla obohacenaněkolika povedenými demonstracemi, kdy jako runtime byl použit aplikační server GlassFish. Následoval přehled webservices stacku aplikačního serveru JBoss v podání Richarda Opálky z firmy RedHat.Jako bývalého člena Metro týmu mě potěšilo, že i druhá prezentace se tohoto projektu dotkla. JBoss totiž použití Metra nabízí jako jednu z variant.Slajdy a stručné představení obou přednášejících lze získat na adrese http://java.cz/detail.do?articleId=16971. A pokud vás zajímá víc,podívejte se i na videa dostupná na následujících adresách:http://mediacast.sun.com/users/jakub.podlesak/media/CZJUG2009.01-Metro-Marek-Potociar-part1.m4v/detailshttp://mediacast.sun.com/users/jakub.podlesak/media/CZJUG2009.01-Metro-Marek-Potociar-part2.m4v/detailshttp://mediacast.sun.com/users/jakub.podlesak/media/CZJUG2009.01-jboss-ws-Richard-Opalka.m4v/detailsPoznámka: Po downloadu by měla videa být přehratelná na Linuxu/Solarisu mplayerem (vyzkoušeno), z platformy Apple byste je měli být schopni přehrát přímo z webu. Na systémech Windows věřím, že po stažení QuickTime Playeru by přehrání mělo být také bez problémů.

26. ledna 2009 proběhlo na půdě katedry počítačů, ČVUT FEL, setkání CZJUG na téma webové služby. Za firmu SUN Microsystems vystoupil Marek Potočiar. Jeho prezentace projektu Metro byla obohacenaněkolika...

REST

Configuring JSON for RESTful Web Services in Jersey 1.0.2

This is an update for a tech tip on configuring JSON in Jersey, which i wrote in October 2008. The way of JSON configuration, suggested in the tech tip, is now deprecated (but still functioning). Here i would like to describe the new API, which will hopefully last (and be supported) a way longer.Notice: you will need to bundle jaxb-impl-2.1.10.jarwith your application in order to take advantage of the recently added JSON NATURAL conventionDeprecated ConfigurationConfiguring JSON format, as described in the tech tip, meant to implement a JAXBContext resolverclass returning an instance of JSONJAXBContext. This principle have not changed.What changed is a way, how the JSONJAXBContext itself is being configured.Lets look at the sample code below (using the deprecated API): @Provider public class MyJAXBContextResolver implements ContextResolver<JAXBContext> { private JAXBContext context; private Class[] types = {StatusInfoBean.class, JobInfoBean.class}; public MyJAXBContextResolver() throws Exception { Map props = new HashMap<String, Object>(); props.put(JSONJAXBContext.JSON_NOTATION, JSONJAXBContext.JSONNotation.MAPPED); props.put(JSONJAXBContext.JSON_ROOT_UNWRAPPING, Boolean.TRUE); props.put(JSONJAXBContext.JSON_ARRAYS, new HashSet<String>(1){{add("jobs");}}); props.put(JSONJAXBContext.JSON_NON_STRINGS, new HashSet<String>(1){{add("pages"); add("tonerRemaining");}}); this.context = new JSONJAXBContext(types, props); } public JAXBContext getContext(Class<?> objectType) { return (types[0].equals(objectType)) ? context : null; } }There you needed to create a property bag, put appropriate configuration options into it,and then pass it to the JSONJAXBContext constructor.Jersey 1.0.2 JSON ConfigurationIn the currently available 1.0.2 Jersey version, a new JSONConfiguration class was introduced to became a central point for JSON configuration options.For creating a new JSONConfiguration instance, a builder pattern is employed.It is not only more user friendly, but also ensures only meaningful JSON options could be combined together.You can compare the following code, with the deprecated example above: @Provider public class MyJAXBContextResolver implements ContextResolver<JAXBContext> { private JAXBContext context; private Class[] types = {StatusInfoBean.class, JobInfoBean.class}; public MyJAXBContextResolver() throws Exception { this.context = new JSONJAXBContext( JSONConfiguration.mapped() .rootUnwrapping(true) .arrays("jobs") .nonStrings("pages", "tonerRemaining") .build(), types); } public JAXBContext getContext(Class<?> objectType) { return (types[0].equals(objectType)) ? context : null; } }You can look at JSONConfiguration javadoc for detailed information on various configuration options.Further SimplificationIf you go a bit further, you can ask if the configuration could be simplified even more.Imagine you have much bigger number of JAXB beans in your model, and they are more complex.It could easily become unmanageable to maintain a reasonable JSON configuration as described so far.Then if you happen to have conflicting non-string/string values and/or arrays/non-arrays elements in your set,you could easily run out of options there.A natural way to overcome above mentioned issues, is to simply use recently introduced Jersey NATURAL JSON notation. Then you need only to: @Provider public class MyJAXBContextResolver implements ContextResolver<JAXBContext> { private JAXBContext context; private Class[] types = {StatusInfoBean.class, JobInfoBean.class}; public MyJAXBContextResolver() throws Exception { this.context = new JSONJAXBContext( JSONConfiguration.natural().build(), types); } public JAXBContext getContext(Class<?> objectType) { return (types[0].equals(objectType)) ? context : null; } }Such configuration is simple from user point of view, but yet very powerful. You do not need to keepvarious configuration options in sync with your actual JAXB beans, and be worried what options to actually use(what exact names, etc.). Jersey will automatically take care aboutserializing Java collections/arrays as JSON arrays, Java booleans as JSON booleans, Java ints as JSON integers,and so on.

This is an update for a tech tip on configuring JSON in Jersey, which i wrote in October 2008. The way of JSON configuration, suggested in the tech tip, is now deprecated (but still functioning)....

REST

Jersey Based Java Client Talking to SmugMug

Jersey provides a great, easy-to-use REST client API. Recently someone wrote to our mailing list the opposite. We probably need to advertise better. Paul initially introduced the API in this blog post almost a year ago. But it is, of course, not the only place to look at. Javadoc for Jersey Client API could be found here.The Jersey Client API could be used pretty easily. However, instead of describing the API in detail, i would just like to present here a real life example. A Jersey based client talking to a 3rd party server application. The server application happens to be SmugMug. A photo sharing service application. I wrote the client application during the last Xmas break, because what was provided by SmugMug did not work well for me. I am happy with my Solaris, but sometimes i wish i have chosen another OS for my laptop ;-)Putting together a functional prototype took me only a couple of hours, and this was mainly thanks to user friendliness of the Jersey Client API designed by Paul. Following is a screenshot of the main screen of the client.I promised not to dig into details, but just for your curiosity. Only the very last statement of the java code below has anything to do with actual invocation of SmugMug API from java using Jersey Client API. All the rest is only about computing a digest for the file being sent, as SmugMug API requires it sent in a special HTTP request header.MessageDigest digest = java.security.MessageDigest.getInstance("MD5");File picFile = new File(picDir, pic);fis = new FileInputStream(picFile);byte[] buf = new byte[8196];int l;while ((l = fis.read(buf)) > -1) { digest.update(buf, 0, l);}String md5hash = asHex(digest.digest());cr = uploadWebResource .path(pic) .header("Content-MD5", md5hash) .header("X-Smug-SessionID", sessionId) .header("X-Smug-Version", "1.2.0") .header("X-Smug-ResponseType", "JSON") .header("X-Smug-AlbumID", car.album.id) .put(ClientResponse.class, picFile);

Jersey provides a great, easy-to-use REST client API. Recently someone wrote to our mailing list the opposite. We probably need to advertise better. Paul initially introduced the API in this blog post a...

CZJUG

Výsledky ankety CZJUGu

V minulých dnech proběhla v rámci CZJUGu menší anketa. Její výsledky jsme se s Dagim rozhodli zveřejnit. Budeme se postupně snažit na jednotlivé podněty reagovat.Respondent statistics:Total respondents108Summary of results1. Počet absolvovaných setkáni026  24%114  13%2-537  34%6 a více31  29%Total answers108 Among 108 respondents the most frequent answer is "2-5".Least frequent answer is "1".2. Sledujete nektera setkaní z archivu AVCAno84  78%Ne24  22%Total answers108 Among 108 respondents the most frequent answer is "Ano".3. Preferujete přednášky v češtiněAno53  49%Ne55  51%Total answers108 Among 108 respondents the most frequent answer is "Ne".4. Vyhovuje Vám misto setkaníAno79  73%Ne29  27%Total answers108 Among 108 respondents the most frequent answer is "Ano".5. Preferujete posluchárnuK177  71%K931  29%Total answers108 Among 108 respondents the most frequent answer is "K1".6. Vyhovuje Vam četnost setkáníAno98  91%Ne10  9%Total answers108 Among 108 respondents the most frequent answer is "Ano".7. Vyhovuje Vám ozvučení posluchárnyAno93  86%Ne15  14%Total answers108 Among 108 respondents the most frequent answer is "Ano".8. Kolik přednášek na setkání preferujete115  14%276  70%317  16%Total answers108 Among 108 respondents the most frequent answer is "2".Least frequent answer is "1".9. Jakou délku setkání preferujete (v minutách)2x4535  32%2x6028  26%Nezáleží45  42%Total answers108 Among 108 respondents the most frequent answer is "Nezáleží".Least frequent answer is "2x60".10. Jakou délku přestávky preferujete (v minutách)512  11%1039  36%1531  29%Nezáleží26  24%Total answers108 Among 108 respondents the most frequent answer is "10".Least frequent answer is "5".11. Omezuje Vás překročení (protažení) časového rámce přednáškyAno16  15%Ne92  85%Total answers108 Among 108 respondents the most frequent answer is "Ne".12. Jaký případný typ komerčního sdělení našich partneru je pro Vás přijatelnějšípřestavkový program85  79%mailling list19  18%Jiné4  4%Total answers108 Other answers:vystoupeni pred prednaskouzadnyje to jednoAmong 108 respondents the most frequent answer is "přestavkový program".Least frequent answer is "Jiné".13. Jaký typ vyvážení za komerční sděleni preferujeteobčerstvení45  42%odborná literatura49  45%conference vouchery8  7%Jiné6  6%Total answers108 Other answers:je mi to jedno, cokoli z vyse uvedeneho mne mirne potesi, ale zilu netrhaobsah prednasek samotny staciat udelaji zajimavou prednasku a tu spoji se svou presentacikterýkoli z uvedenýchnechal bych na fantaziji sdelujiciho (treba muze prijit s necim novym, originalnim)Among 108 respondents the most frequent answer is "odborná literatura".Least frequent answer is "Jiné".14. Minulá setkániAndroid - Michal Šrajer, Pavel PetřekNebyl jsem77  71%Spokojen30  28%Nespokojen2  2%OSGi - Michal MalohlavaNebyl jsem76  70%Spokojen27  25%Nespokojen6  6%Java ME a Mobility Pack - Petr SuchomelNebyl jsem69  63%Spokojen34  31%Nespokojen6  6%Groovy - Václav PechNebyl jsem70  64%Spokojen37  34%Nespokojen2  2%Jython - Štefan HavlíčekNebyl jsem78  72%Spokojen16  15%Nespokojen15  14%Seeing Aspects in Web Application Architectures - Andrea ProvaglioNebyl jsem83  76%Spokojen24  22%Nespokojen2  2%Performance - Oldřich KepkaNebyl jsem81  74%Spokojen25  23%Nespokojen3  3%JBoss Seam - Petr FerschmannNebyl jsem75  69%Spokojen33  30%Nespokojen1  1%REST - Jakub PodlešákNebyl jsem74  68%Spokojen33  30%Nespokojen2  2%Glassfish v3 - Kohsuke KawaguchiNebyl jsem83  76%Spokojen23  21%Nespokojen3  3%"Android - Michal Šrajer, Pavel Petřek" most frequent answer is "Nebyl jsem". The least frequent answer is "Nespokojen"."OSGi - Michal Malohlava" most frequent answer is "Nebyl jsem". The least frequent answer is "Nespokojen"."Java ME a Mobility Pack - Petr Suchomel" most frequent answer is "Nebyl jsem". The least frequent answer is "Nespokojen"."Groovy - Václav Pech" most frequent answer is "Nebyl jsem". The least frequent answer is "Nespokojen"."Jython - Štefan Havlíček" most frequent answer is "Nebyl jsem". The least frequent answer is "Nespokojen"."SeeingAspects in Web Application Architectures - Andrea Provaglio" mostfrequent answer is "Nebyl jsem". The least frequent answer is"Nespokojen"."Performance - Oldřich Kepka" most frequent answer is "Nebyl jsem". The least frequent answer is "Nespokojen"."JBoss Seam - Petr Ferschmann" most frequent answer is "Nebyl jsem". The least frequent answer is "Nespokojen"."REST - Jakub Podlešák" most frequent answer is "Nebyl jsem". The least frequent answer is "Nespokojen"."Glassfish v3 - Kohsuke Kawaguchi" most frequent answer is "Nebyl jsem". The least frequent answer is "Nespokojen".15. Máte zájem slyšet přednášky na téma dalších JVM jazyků (Scala, Groovy, Ruby)Ano80  74%Ne28  26%Total answers108 Among 108 respondents the most frequent answer is "Ano".16. Máte zájem slyšet alternativní pojetí přednášek např. diskusní panel, souboj dvou technologiíAno100  93%Ne8  7%Total answers108 Among 108 respondents the most frequent answer is "Ano".17. Na příštích setkáních preferuji následující prezentaceiBatis1 - chci nejvice17  16%226  24%337  34%4 - chci nejméně28  26%Wicket1 - chci nejvice32  30%229  27%331  29%4 - chci nejméně16  15%Tapestry1 - chci nejvice18  17%235  32%332  30%4 - chci nejméně23  21%JSF1 - chci nejvice36  33%230  28%322  20%4 - chci nejméně20  19%Cloud Computing1 - chci nejvice22  20%244  41%326  24%4 - chci nejméně16  15%OpenOffice (porgramové použití z Javy)1 - chci nejvice36  33%230  28%325  23%4 - chci nejméně17  16%OpenSolaris (nástroje pro vývojáře)1 - chci nejvice9  8%220  19%329  27%4 - chci nejméně50  46%WebService stack: Metro, JBoss1 - chci nejvice44  41%227  25%319  18%4 - chci nejméně18  17%Java FX1 - chci nejvice37  34%235  32%320  19%4 - chci nejméně16  15%Grails1 - chci nejvice20  19%233  31%337  34%4 - chci nejméně18  17%"iBatis" most frequent answer is "3". The least frequent answer is "1 - chci nejvice"."Wicket" most frequent answer is "1 - chci nejvice". The least frequent answer is "4 - chci nejméně"."Tapestry" most frequent answer is "2". The least frequent answer is "1 - chci nejvice"."JSF" most frequent answer is "1 - chci nejvice". The least frequent answer is "4 - chci nejméně"."Cloud Computing" most frequent answer is "2". The least frequent answer is "4 - chci nejméně"."OpenOffice(porgramové použití z Javy)" most frequent answer is "1 - chcinejvice". The least frequent answer is "4 - chci nejméně"."OpenSolaris(nástroje pro vývojáře)" most frequent answer is "4 - chci nejméně".The least frequent answer is "1 - chci nejvice"."WebService stack: Metro, JBoss" most frequent answer is "1 - chci nejvice". The least frequent answer is "4 - chci nejméně"."Java FX" most frequent answer is "1 - chci nejvice". The least frequent answer is "4 - chci nejméně"."Grails" most frequent answer is "3". The least frequent answer is "4 - chci nejméně".18. Mám zájem prezentovat na CZJUGAno10  9%Ne98  91%Total answers108 Among 108 respondents the most frequent answer is "Ne".19. Můj zaměstnavatel má zájem prentovat na CZJUGAno9  8%Ne48  44%Nevím51  47%Total answers108 Among 108 respondents the most frequent answer is "Nevím".Least frequent answer is "Ano".20. Můj zaměstnavatel má zájem komerčně přispět k rozvoji CZJUGAno11  10%Ne97  90%Total answers108 Among 108 respondents the most frequent answer is "Ne".21. Chci něco vzkázat organizátorůmNe78  72%Ano30  28%Total answers108 Other answers:Dobra prace!Dobra prace!!!Diky!Jen tak dál!Jsem z Brna, takze bych uvital dalsi akci zde. Jinak mi zustava jen video ...Díky za skvělou práci.Díky.prosím zkuste střídat Prahu s něčím jiným (Brno, Olomouc, Jihlava)Keep up good work. :)ahoj, jako neprazak bych velice ocenil zaznamy z prazentaci, dikydekujiDobře to děláte, jen tak dál až dozraju, tak možná budu i něco prezentovat.Nepiste porad tolik "spamu" na mail prosimDěkkuji. Jsem vázán na AVC. Také díkyhlavne zalezi na prdnaskach, zbytek je omacka ... a oboji zvladate perfektne !!!Zajimala by me prednaska na tema Java Content Repository, Apache Jackrabbitnevim, ktera poslucharna je K1 a ktera K9, takze mou odvpoved na prislusnou otazku prosim ignorujte :)záznamy z akcí.. audio/videodiky a hodne zdaruPravidelnéschůzky v době, kdy mám pevnýá program mi brání zúčastnit se řady akcí.Přivítal bych pozdější hodinu nebo jiný den než pondělí.zatial som spokojny. Dobra praca.Odvádíte skvělou práci a doufám, že budete úspěšní i nadále.díky za organizaci :-) (do dotazníku dejte víc možností "nevím")Dobra prace!preferoval bych kdyby setkání byla v různé dny v týdnu, aby byla větší šance že se rozumně dostanu alespoň na některéDiky :)Díky!!!ChudáciHodně úspěchů!Super prednasky, zlepsit kvalitu audia v nahravkach AVC.Among 108 respondents the most frequent answer is "Ne".22. Díky za Váš čas a podporu rozvoje CZJUG.

V minulých dnech proběhla v rámci CZJUGu menší anketa. Její výsledky jsme se s Dagim rozhodli zveřejnit. Budeme se postupně snažit na jednotlivé podněty reagovat. Respondent statistics: Total...

REST

Simple Jersey Web App With Maven Take 2: Replacing Tomcat With GlassFish

Yesterday, i wrote about how to put together a simple Jersey based RESTful web applicationusing just CLI and maven. I have ended with running the application using mvn tomcat:run. In this entry i would like to show, ho to easily update the pom.xml file, so that you can usemvn glassfish:runinstead. I.e. how to run the thing on GlassFish V3 application server instead of Tomcat. Updating Your pom.xmlFollowing is the updated pom.xml. Newly added pieces are red:<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>my.example.com</groupId> <artifactId>SimpleRESTApp</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>SimpleRESTApp Maven Webapp</name> <url>http://maven.apache.org</url> <repositories> <repository> <id>glassfish-repository</id> <name>Java.net Repository for Glassfish</name> <url>http://download.java.net/maven/glassfish</url> </repository> <repository> <id>maven2-repository.dev.java.net</id> <name>Java.net Repository for Maven</name> <url>http://download.java.net/maven/2/</url> <layout>default</layout> </repository> </repositories><pluginRepositories> <pluginRepository> <id>maven2.java.net</id> <name>Java.net Repository for Maven 2</name> <url>http://download.java.net/maven/2</url> </pluginRepository> </pluginRepositories> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey</artifactId> <version>0.8-ea-SNAPSHOT</version> </dependency> </dependencies> <build> <plugins><plugin> <groupId>org.glassfish</groupId> <artifactId>maven-glassfish-plugin</artifactId> <version>1.0-alpha-4</version> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.5</source> <target>1.5</target> </configuration> </plugin> </plugins> <finalName>SimpleRESTApp</finalName> </build></project>A simple update, isn't it? Running The WebAppNow you can try to type:mvn glassfish:runand will get:[INFO] Scanning for projects...[INFO] Searching repository for plugin with prefix: 'glassfish'.[INFO] ------------------------------------------------------------------------[INFO] Building SimpleRESTApp Maven Webapp[INFO] task-segment: [glassfish:run][INFO] ------------------------------------------------------------------------[INFO] Preparing glassfish:run[INFO] [resources:resources][INFO] Using default encoding to copy filtered resources.[INFO] [compiler:compile][INFO] Nothing to compile - all classes are up to date[INFO] [glassfish:run]Jun 3, 2008 10:55:20 AM com.sun.enterprise.v3.server.AppServerStartup runINFO: HK2 initialized in 316 msJun 3, 2008 10:55:20 AM com.sun.enterprise.v3.server.AppServerStartup runINFO: com.sun.enterprise.naming.impl.ServicesHookup@16089a5 Init done in 323 msJun 3, 2008 10:55:20 AM com.sun.enterprise.v3.server.AppServerStartup runINFO: com.sun.enterprise.v3.server.Globals@15fb38 Init done in 325 msJun 3, 2008 10:55:20 AM com.sun.enterprise.v3.server.AppServerStartup runINFO: com.sun.enterprise.v3.server.SystemTasks@878c4c Init done in 330 msJun 3, 2008 10:55:20 AM com.sun.enterprise.v3.server.AppServerStartup runINFO: com.sun.enterprise.v3.services.impl.HouseKeeper@8f9a32 Init done in 333 msJun 3, 2008 10:55:20 AM com.sun.enterprise.v3.server.AppServerStartup runINFO: com.sun.enterprise.v3.services.impl.CmdLineParamProcessor@1581e80 Init done in 336 msJMXMP connector server URL = service:jmx:jmxmp://localhost:8888Jun 3, 2008 10:55:21 AM com.sun.enterprise.v3.services.impl.GrizzlyProxy startINFO: Listening on port 8080Jun 3, 2008 10:55:21 AM com.sun.enterprise.v3.server.AppServerStartup runINFO: com.sun.enterprise.v3.services.impl.GrizzlyService@5dfaf1 startup done in 962 msJun 3, 2008 10:55:21 AM com.sun.enterprise.v3.services.impl.ApplicationLoaderService postConstructINFO: loader service postConstruct started at 1212483321145Jun 3, 2008 10:55:21 AM com.sun.enterprise.v3.server.AppServerStartup runINFO: Application Loader startup done in 993 msJun 3, 2008 10:55:21 AM com.sun.enterprise.v3.server.AppServerStartup runINFO: Glassfish v3 started in 994 msJun 3, 2008 10:55:25 AM com.sun.enterprise.web.WebModuleContextConfig authenticatorConfigSEVERE: webModuleContextConfig.missingRealmJun 3, 2008 10:55:25 AM com.sun.jersey.api.core.PackagesResourceConfig initINFO: Scanning for root resource and provider classes in the packages: com.example.myJun 3, 2008 10:55:25 AM com.sun.jersey.api.core.PackagesResourceConfig initINFO: Root resource classes found: class com.example.my.SimpleResourceJun 3, 2008 10:55:25 AM com.sun.jersey.api.core.PackagesResourceConfig initINFO: Provider classes found:Hit ENTER for redeployPlease note, that GlassFish has started in less than a second!Testing The REST ResourceNow we can also test the web resource:%curl -i http://localhost:8080/SimpleRESTApp/greetingHTTP/1.1 200 OKX-Powered-By: Servlet/2.5Server: GlassFish/v3Content-Type: text/plainTransfer-Encoding: chunkedDate: Tue, 03 Jun 2008 09:01:08 GMTHi there

Yesterday, i wrote about how to put together a simple Jersey based RESTful web application using just CLI and maven. I have ended with running the application using mvn tomcat:run. In this entry i...

REST

Building Simple Jersey Web App With Maven

I have recently configured our Hudson server to push latest Jersey snapshots to maven repository at https://maven2-repository.dev.java.net/.Thanks to Martin Grotzke for his kind help!I am pretty new to maven, and wanted to make sure Jersey related jars are deployed just fine and could be easily used. Following is steps to create a new Jersey based web application from scratch.I will be using only CLI and maven.Create a New Project LayoutAt the beginning we need to create a new web project: mvn archetype:create -DgroupId=my.example.com -DartifactId=SimpleRESTApp \\ -DarchetypeArtifactId=maven-archetype-webappWhich should print out something like:[INFO] Scanning for projects...[INFO] Searching repository for plugin with prefix: 'archetype'.[INFO] ------------------------------------------------------------------------[INFO] Building Maven Default Project[INFO] task-segment: [archetype:create] (aggregator-style)[INFO] ------------------------------------------------------------------------Downloading: http://repo1.maven.org/maven2/my/example/com/wagon-http-shared/1.0-beta-2/wagon-http-shared-1.0-beta-2.pomDownloading: http://repo1.maven.org/maven2/my/example/com/wagon-http-shared/1.0-beta-2/wagon-http-shared-1.0-beta-2.pom[INFO] Setting property: classpath.resource.loader.class => 'org.codehaus.plexus.velocity.ContextClassLoaderResourceLoader'.[INFO] Setting property: velocimacro.messages.on => 'false'.[INFO] Setting property: resource.loader => 'classpath'.[INFO] Setting property: resource.manager.logwhenfound => 'false'.[INFO] [archetype:create][INFO] Defaulting package to group ID: my.example.com[INFO] ----------------------------------------------------------------------------[INFO] Using following parameters for creating OldArchetype: maven-archetype-webapp:RELEASE[INFO] ----------------------------------------------------------------------------[INFO] Parameter: groupId, Value: my.example.com[INFO] Parameter: packageName, Value: my.example.com[INFO] Parameter: basedir, Value: /export/home/japod/workspace/cli-jersey-app[INFO] Parameter: package, Value: my.example.com[INFO] Parameter: version, Value: 1.0-SNAPSHOT[INFO] Parameter: artifactId, Value: SimpleRESTApp[INFO] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* End of debug info from resources from generated POM \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*[INFO] OldArchetype created in dir: /export/home/japod/workspace/cli-jersey-app/SimpleRESTApp[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESSFUL[INFO] ------------------------------------------------------------------------[INFO] Total time: 3 secondsAnd create the following subtree:SimpleRESTApp |-src |---main |-----resources |-----webapp |-------WEB-INFCreating a REST Resource ClassYou will need to add at least one resource class.cd SimpleRESTAppmkdir -p src/main/java/com/example/myvim src/main/java/com/example/my/SimpleResource.javaIt could have the following content:package com.example.my;import javax.ws.rs.GET;import javax.ws.rs.ProduceMime;import javax.ws.rs.Path;// The Java class will be hosted at the URI path "/greeting"@Path("greeting")public class SimpleResource { // and implement the following GET method @GET @ProduceMime("text/plain") public String getGreeting() { return "Hi there"; }}Adding Necessary Dependencies Into Our POMThen we will need to introduce some dependencies at our POM file,it could be done like follows:<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>my.example.com</groupId> <artifactId>SimpleRESTApp</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>SimpleRESTApp Maven Webapp</name> <url>http://maven.apache.org</url><repositories> <repository> <id>maven2-repository.dev.java.net</id> <name>Java.net Repository for Maven</name> <url>http://download.java.net/maven/2/</url> <layout>default</layout> </repository> </repositories> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency><dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey</artifactId> <version>0.8-ea-SNAPSHOT</version> </dependency> </dependencies> <build><plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>tomcat-maven-plugin</artifactId> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.5</source> <target>1.5</target> </configuration> </plugin> </plugins> <finalName>SimpleRESTApp</finalName> </build></project>We have added a new repository, tomcat plugin and jersey dependency.Configuring Jersey Servlet AdapterNow the last step before we can actually run the web application is to properly configure Jersey container. I will be using a servlet adapter and the configurationneeds to be placed in our web.xml file:vim src/main/webapp/WEB-INF/web.xmland add the following red lines there:<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" ><web-app> <display-name>Archetype Created Web Application</display-name><servlet> <servlet-name>Jersey Web Application</servlet-name><servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> <init-param><param-name>com.sun.jersey.config.property.resourceConfigClass</param-name><param-value>com.sun.jersey.api.core.PackagesResourceConfig</param-value> </init-param> <init-param> <param-name>com.sun.jersey.config.property.packages</param-name> <param-value>com.example.my</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Jersey Web Application</servlet-name> <url-pattern>/\*</url-pattern> </servlet-mapping></web-app>Running The ApplicationNow to get the application running, you can simply type:mvn tomcat:runYou should see something like:[INFO] Scanning for projects...[INFO] Searching repository for plugin with prefix: 'tomcat'.[INFO] ------------------------------------------------------------------------[INFO] Building SimpleRESTApp Maven Webapp[INFO] task-segment: [tomcat:run][INFO] ------------------------------------------------------------------------[INFO] Preparing tomcat:run[INFO] [resources:resources][INFO] Using default encoding to copy filtered resources.[INFO] [compiler:compile][INFO] Compiling 1 source file to /export/home/japod/workspace/cli-jersey-app/SimpleRESTApp/target/classes[INFO] [tomcat:run][INFO] Creating Tomcat server configuration at /export/home/japod/workspace/cli-jersey-app/SimpleRESTApp/target/tomcat[INFO] Starting tomcat server[INFO] Starting Servlet Engine: Apache Tomcat/5.5.15[INFO] XML validation disabledJun 2, 2008 3:47:17 PM com.sun.jersey.api.core.PackagesResourceConfig initINFO: Scanning for root resource and provider classes in the packages: com.example.myJun 2, 2008 3:47:17 PM com.sun.jersey.api.core.PackagesResourceConfig initINFO: Root resource classes found: class com.example.my.SimpleResourceJun 2, 2008 3:47:17 PM com.sun.jersey.api.core.PackagesResourceConfig initINFO: Provider classes found:Jun 2, 2008 3:47:18 PM com.sun.jersey.impl.wadl.WadlFactory createWadlResourceWARNING: WADL generation is disabled because JAXB jars are not included in the java class path. To enable WADL include JAXB 2.x jars in the java class path.[INFO] Initializing Coyote HTTP/1.1 on http-8080[INFO] Starting Coyote HTTP/1.1 on http-8080Testing Your REST ResourceTo check your resource works, you can try:% curl -i http://localhost:8080/SimpleRESTApp/greeting HTTP/1.1 200 OKServer: Apache-Coyote/1.1Content-Type: text/plainTransfer-Encoding: chunkedDate: Mon, 02 Jun 2008 13:49:18 GMTHi there

I have recently configured our Hudson server to push latest Jersey snapshots to maven repository at https://maven2-repository.dev.java.net/. Thanks to Martin Grotzke for his kind help! I am pretty new...

REST

Workarounding Cross-domain Restriction With Jersey

Having a JSON generating REST resource, you can consume provided data in your web page using JavaScript pretty easily. To access dataat your own site you can obviously make a HttpRequest from JavaScript code.To access data from another site, you will need to workarounda cross-domain restriction somehow. Two possible approaches are describedat Dan Theurer's blog entries here and here.In this entry i will show how to add the JavaScript representation option to your Jersey based REST resource, so that besides { some JSON data}when your client asks for http://.../myResource.json,you will be able to return also something like myFunc({ some JSON data})when it asks for http://.../myResource.js?callback=myFuncThen the technique basically works like follows:You have a callback function myFunc defined in JavaScript, which processes provided JSON dataIn your page you dynamically create following HTML code: <script src="http://.../myResource.js?callback=myFunc"/>, which automatically invokes your callback function on the returned dataMime-Type in URIThe key thing here is, that you do notwant to specify desired mime-type (JavaScript) in anywhere but the URI itself.Otherwise you would not be able to simply add the script tag to your page.To achieve this in Jersey, you will need to add some media-type mappings to your ResourceConfig.For a servlet container you can extendexisting ServletContainer like this:public class MyServletContainer extends ServletContainer { @Override public void initiate(ResourceConfig rc, WebApplication wa ) { super.initiate(rc, wa); rc.getMediaTypeMappings().put("json", MediaType.valueOf("application/json")); rc.getMediaTypeMappings().put("xml", MediaType.valueOf("application/xml")); rc.getMediaTypeMappings().put("js", MediaType.valueOf("text/javascript")); }}And use it in your web.xml:<servlet> <servlet-name>Jersey Web Application</servlet-name> <servlet-class>my.container.MyServletContainer</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Jersey Web Application</servlet-name> <url-pattern>/resources/\*</url-pattern> </servlet-mapping>For other containers (http/grizzly) you can just pass your ResourceConfig directly to ContainerFactoryJavaScript Message Bode Writer ProviderNow you will need to have a custom MessageBodyWriter providerto serialize JAXB beans to the above mentioned JavaScript format.You can use the following code:@Provider@ProduceMime("text/javascript")public class JavaScriptWriterProvider implements MessageBodyWriter<Object> { private static Map<Class, JAXBContext> jaxbContexts = new WeakHashMap<Class, JAXBContext>(); @Context private ContextResolver<JAXBContext> cr; @Context UriInfo uriInfo; protected final JAXBContext getJAXBContext(Class type) throws JAXBException { if (cr != null) { JAXBContext c = cr.getContext(type); if (c != null) return c; } synchronized (jaxbContexts) { JAXBContext context = jaxbContexts.get(type); if (context == null) { context = JAXBContext.newInstance(type); jaxbContexts.put(type, context); } return context; } } public boolean isWriteable(Class<?> c, Type t, Annotation[] as) { return (c.getAnnotation(XmlRootElement.class) != null) || JAXBElement.class.isAssignableFrom(c); } public long getSize(Object arg0) { return -1; } public void writeTo(Object o, Class<?> clazz, Type type, Annotation[] as, MediaType mediaType, MultivaluedMap<String, Object> headers, OutputStream entityStream) throws IOException, WebApplicationException { boolean isJaxbElementCase = JAXBElement.class.isAssignableFrom(clazz); try { JAXBContext context = getJAXBContext(isJaxbElementCase ? ((JAXBElement)o).getDeclaredType() : o.getClass()); Marshaller marshaller = context.createMarshaller(); String fcName = uriInfo.getQueryParameters().getFirst("callback"); if (fcName == null) { fcName = "myFunction"; } entityStream.write((fcName + "(").getBytes()); if (marshaller instanceof JSONMarshaller) { marshaller.setProperty(JSONJAXBContext.JSON_ENABLED, Boolean.TRUE); marshaller.setProperty(JSONJAXBContext.JSON_ROOT_UNWRAPPING, Boolean.TRUE); marshaller.marshal(o, new OutputStreamWriter(entityStream)); } else { marshaller.marshal(o, new JsonXmlStreamWriter( new OutputStreamWriter(entityStream), true)); } entityStream.write(")".getBytes()); } catch (JAXBException cause) { throw ThrowHelper.withInitCause(cause, new IOException(ImplMessages.ERROR_MARSHALLING_JAXB(o.getClass())) ); } }}REST ResourcesFinally you can implement your resources. The implementation could be as simple as this:@Path("js-test")@ProduceMime({"text/javascript", "application/json", "application/xml"})public class JavaScriptResource { @GET @Path("jaxb-bean") public SimpleJaxbBean getJAXBBean() { return new SimpleJaxbBean(); } @GET @Path("jaxb-element") public JAXBElement<SimpleBean> getJAXBElement() { return new JAXBElement<SimpleBean>(new QName("wrapper"), SimpleBean.class, new SimpleBean()); }}Where SimpleBean and SimpleJaxbBean are (for sake of simplicity ) implemented like follows:public class SimpleBean { public String value = "jaxb element"; public SimpleBean() { } public SimpleBean(String v) { this.value = v; }}@XmlRootElementpublic class SimpleJaxbBean { public String value = "jaxb bean"; public SimpleJaxbBean() { } public SimpleJaxbBean(String v) { this.value = v; }}It shows, that even POJO could be handled this way and transformed into JSON and JavaScript.A small sample application with source code and bundled Jersey libs is available here. You can also download a NetBeans zipped project files here. After deploying the application, the following requests are equivalent. Please note that the JavaScript callback function name is customizable (see the callback query parameter in the second request).%curl -i -HAccept:text/javascript http://localhost:11750/JavaScriptApp/resources/js-test/jaxb-beanHTTP/1.1 200 OKX-Powered-By: Servlet/2.5Server: Sun Java System Application Server 9.1_01Content-Type: text/javascriptTransfer-Encoding: chunkedDate: Mon, 26 May 2008 12:39:32 GMTmyFunction({"value":"jaxb bean"})%curl -i "http://localhost:11750/JavaScriptApp/resources/js-test/jaxb-bean.js?callback=myFunction HTTP/1.1 200 OKX-Powered-By: Servlet/2.5Server: Sun Java System Application Server 9.1_01Content-Type: text/javascriptTransfer-Encoding: chunkedDate: Mon, 26 May 2008 12:41:00 GMTmyFunction({"value":"jaxb bean"})Look at Dan Theurer's blog entry for information how the client-side JavaScript could look like.

Having a JSON generating REST resource, you can consume provided data in your web page using JavaScript pretty easily. To access dataat your own site you can obviously make a HttpRequest...

REST

jMaki Putting Data to Jersey

In this post I have described how to make jMaki widgets consume Jersey based web resources. In a read-only manner. Here I would like to show how to close the circle and make jMaki widgets push an updated information back to the Jersey. Many thanks to Greg Murray who has spent some time with me on Monday to put the following piece of code together. The most important part of it is emphasized and shows how to actually make a PUT requestusing jMaki function doAjaxjmaki.subscribe("/dojo/etable/onCellEdit", function(arg) { jmaki.doAjax({ url: "/jMakiBackend/webresources/printers/ids/"+arg.row, headers:[{name:"Accept", value:"application/json"}], callback:function(ar){ var i = eval("("+ar.responseText+")"); var cols = ["id", "model", "url", "location"] eval("i." + cols[arg.column]+"='"+arg.value+"'");jmaki.doAjax({ url: "jMakiBackend/webresources/printers/ids/"+arg.row, headers:[{name:"Content-type", value:"application/json"}], method:"PUT", body : jmaki.json.serialize(i) }) } })})All you need to make it work is to implement the simple front-end jMaki application (as described here)change the table widget to editable dojo table (replace name="yahoo.dataTable" with name="dojo.etable" in the index.jsp page. it is really simple, isn't it?)and add the above mentioned snippet into your glue.jsThen you should be able to update an information in the table widget and see it updated also in the underlaying web resource representation. I have not tried, but suppose that updating printer ids shouldn't work ;-)

In this post I have described how to make jMaki widgets consume Jersey based web resources. In a read-only manner. Here I would like to show how to close the circle and make jMaki widgets push...

REST

Missing Brackets At JSON One-Element Arrays In Jersey

It is a bit uncomfortable, but if you need to deal with arrays in JSON produced by Jersey,you will need to provide a custom JAXB context resolver to make sure brackets are properly usedin one-element arrays.As Reece Garrett pointed out,the very same issue was hit (and resolved) in Jettison as well.What is exactly the issue?Lets say, you have the following JAXB bean @XmlRootElement public class ArrayWrapper { public List<String> list = new LinkedList<String>(); }and want to get JSON out of it. The issue is, that after ArrayWrapper aw = new ArrayWrapper(); aw.list.add("one");you will get{"list":"one"}while if you add one more element aw.list.add("two");you will get this:{"list":["one", "two"]}Please note the missing brackets at the former case.SolutionIn order to have the brackets properly used also for one-element arrays you need to provide yourcustom JAXB context through which you can tell the underlying JSON writer what is an array.It can look like this: @Provider public class JAXBContextResolver implements ContextResolver<JAXBContext> { private JAXBContext context; private Class[] types = {ArrayWrapper.class}; public JAXBContextResolver() throws Exception { Map props = new HashMap<String, Object>(); props.put(JSONJAXBContext.JSON_NOTATION, "MAPPED"); props.put(JSONJAXBContext.JSON_ROOT_UNWRAPPING, Boolean.TRUE);props.put(JSONJAXBContext.JSON_ARRAYS, "[\\"list\\"]"); this.context = new JSONJAXBContext(types, props); } public JAXBContext getContext(Class<?> objectType) { return (types[0].equals(objectType)) ? context : null; } }JSONJAXBContext.JSON_ARRAYS property here takes a JSON array with names of elements representing arraysin you JAXB beans. Having the resolver in place for the example above you will now obtain{"list":["one"]}

It is a bit uncomfortable, but if you need to deal with arrays in JSON produced by Jersey, you will need to provide a custom JAXB context resolver to make sure brackets are properly usedin one-element...

REST

jMaki Widgets Talking To Jersey Resources In JSON

In the recent post, i have announced an improvement in JSON format produced by Jersey. Here i would like to show how you can easily consume the new format by jMaki widgets. An example of what you can get is shown below.Jersey back-end resources are already available within Jersey examples as jMakiBackend web application. You just need to obtain the latest Jersey bundle and then build and deploy the jMakiBackend example via following:% cd jersey-0.6-ea/examples/jMakiBackend% ant% $AS_HOME/bin/asadmin start-domain% $AS_HOME/bin/asadmin deploy dist/jMakiBackend.warYou can then test your Jersey resources:% curl http://localhost:8080/jMakiBackend/webresources/printers/jMakiTable{"columns":[{"id":"id","label":"Printer ID"},{"id":"model","label":"Model"},{"id":"url","label":"URL"},{"id":"location","label":"Location"}],"rows":[{"id":"P05","model":"Xerox345","url":"lpd://p05","location":"room 543"},{"id":"P02","model":"OKI123","url":"lpd://p02","location":"room 12"},{"id":"P06","model":"Xerox345","url":"lpd://p06","location":"room 203"},{"id":"P03","model":"OKI123","url":"lpd://p03","location":"room 133"},{"id":"P01","model":"OKI123","url":"lpd://p01","location":"room 1"}]}%curl http://localhost:8080/jMakiBackend/webresources/printers/jMakiTree {"root":{"label":"printers","expanded":true,"children":[{"label":"Model Xerox345","expanded":true,"children":[{"label":"P05 @ room 543","expanded":false},{"label":"P06 @ room 203","expanded":false}]},{"label":"Model OKI123","expanded":true,"children":[{"label":"P02 @ room 12","expanded":false},{"label":"P03 @ room 133","expanded":false},{"label":"P01 @ room 1","expanded":false}]}]}}Connecting jMaki widgets is very simple.You just create a new web application in Netbeans 6 (provided you have jMaki/AJAX plugin already installed), drag and drop Yahoo table or Dojo tree widget to your page and set the widget service parameter to an appropriate URI.Besides the two jMaki friendly resources, you can also manipulate the underlaying data via http://localhost:8080/jMakiBackend/webresources/printers/ids/{printerid} URI.GET, PUT and DELETE HTTP methods are available on it providing access to getting, creating/updating and deleting particular printer records.%curl http://localhost:8080/jMakiBackend/webresources/printers/ids/P01{"id":"P01","model":"OKI123","url":"lpd://p01","location":"room 1"}%curl -i -X PUT -HContent-type:application/json \\ --data '{"id":"P01","model":"OKI123456","url":"lpd://p01.b02","location":"big showroom"}' \\http://localhost:8080/jMakiBackend/webresources/printers/ids/P01HTTP/1.1 204 No ContentX-Powered-By: Servlet/2.5Server: Sun Java System Application Server 9.1.1Date: Sat, 23 Feb 2008 08:15:01 GMT% curl -i -X DELETE http://localhost:8080/jMakiBackend/webresources/printers/ids/P01HTTP/1.1 204 No ContentX-Powered-By: Servlet/2.5Server: Sun Java System Application Server 9.1.1Date: Sat, 23 Feb 2008 08:17:29 GMTFor detailed information on JAXB beans used for the jMaki models please look at the jMakiBackend example code here and here

In the recent post, i have announced an improvement in JSON format produced by Jersey. Here i would like to show how you can easily consume the new format by jMaki widgets.An example of what you can...

REST

Better JSON Available In Jersey

Since today a better support for JSON data generated out of JAXB beans is available in Jersey.The main improvement is a simpler default JSON data format.Badgerfish convention was replaced by a new one, a slightly simplified so called mapped convention from Jettison. JSON convention used for particular beans is now also fully configurable by the end user.I will show how the configuration could be done below.The main differences between available formats could be described using the following example.Lets start with a very simple JAXB bean. You can see the source code, XML output and thenall formats you can get from Jersey resource:@XmlRootElementpublic static class SimpleJaxbBean { public String name = "Franz"; public String surname = "Kafka";}XML output:<simpleJaxbBean> <name>Franz</name> <surname>Kafka</surname></simpleJaxbBean>Badgerfish format:{"simpleJaxbBean":{"name":{"$":"Franz"},"surname":{"$":"Kafka"}}}Mapped format (Jettison):{"simpleJaxbBean":{"name":"Franz","surname":"Kafka"}}and finally Jersey default format:{"name":"Franz","surname":"Kafka"}If you want to control, which format is actually used for which JAXB bean,you can do it by providing Jersey runtime with your own custom JAXBContext classesvia implementing custom ContextResolver.You can get inspired by following example:@Path("/jsonFormats")public class SimpleJsonResource {@Providerpublic static class JAXBContextResolver implements ContextResolver<JAXBContext> { private JAXBContext context; private Class[] types = {SimpleJaxbBean.class};public JAXBContextResolver() throws Exception { Map<String, Object> props = new HashMap<String, Object>(); props.put(JSONJAXBContext.JSON_NOTATION, "MAPPED_JETTISON"); props.put(JSONJAXBContext.JSON_ROOT_UNWRAPPING, Boolean.FALSE); this.context = new JSONJAXBContext(types, props); }public JAXBContext getContext(Class<?> objectType) { return (types[0].equals(objectType)) ? context : null; } } @XmlRootElement public static class SimpleJaxbBean { public String name = "Franz"; public String surname = "Kafka"; } @GET @ProduceMime({"application/json", "application/xml"}) public SimpleJaxbBean getJson() { return new SimpleJaxbBean(); }}The following options are available for the JSONJAXBContext.JSON_NOTATIONproperty, where the first one is the default value:MAPPEDMAPPED_JETTISONBADGERFISHIn the future i plan to add more properties so that the JSON serialization and deserializationis highly configurable.

Since today a better support for JSON data generated out of JAXB beans is available in Jersey. The main improvement is a simpler default JSON data format.Badgerfish convention was replaced by a new...

Hezky česky

Jak mě roboti (zase) dostali

Motto: Nesnažte se být rychlejší než automat V pondělí na prezentaci CZJUGu se mi povedl parádní generálský efekt s pluginem do Netbeans 6.0. Včera mi autoři pluginu vysvětlili a dnes jsem si oveřil, ze příčinou byla pomalá reakce "umělé inteligence" pluginu.O co jde? RESTful Web Services plugin se pro danou webovou aplikaci aktivuje na pozadí. Tedy pokud je nainstalován: musíte si jej napřed stáhnout z Netbeans 6.0 beta update centra (viz. obrázek)Plugin obsahuje knihovny projektu Jersey, několik "wizardů" pro generování RESTových "resources"a dale propracovaného testovacího klienta. Pro aplikaci, kde jsou použity JSR-311 anotace plugin automaticky nakonfiguruje použití potřebných knihoven, které jsou pak přibaleny i do distribučního war archivu. Tento proces je naprosto transparentní a uživatelem nekontrolovatelný.Jak to zkazitPokud pro psaní svých RESTových "resources" nepoužijete poskytované wizardy, aktivuje se plugin následujicím způsobem. V editoru napíšete JSR-311 anotaci, například @Path("/brumla"). Někde ve vnitřnostech Netbeans se v této chvíli vygeneruje událost, na kterou čeká i náš REST plugin: neznámá anotace. Neznámá proto,ze není použito plně kvalifikované jméno a chybí import příslušného balíčku. Ve chvíli, kdy je REST plugin na věc upozorněn, doplní do cesty projektu potřebné knihovny. Když jej ale předběhnete a stisknete [Ctrl][Shift]-I, abyste doplnili importy chybějících balíčků, stane se vám to, co mě při prezentaci a co je vidět na obrázku.Použil se špatný balíček! Mělo to být import javax.ws.rs.Path;, jenže bylo použito pouze to, co bylo v dané chvíli k dispozici. Jak z toho ven?Buď import rovnou opravte nebo ho smažte a chvíli počkejte (tak 5 vteřin). Pak zkuste znovu [Ctrl][Shift]-I.Pokud uvidíte něco jako je na obrázku, máte vyhráno.Přesvědčili jste automat, že Jersey knihovny ve svém projektu opravdu chcete, a on je tam doplnil.

Motto: Nesnažte se být rychlejší než automat V pondělí na prezentaci CZJUGu se mi povedl parádní generálský efekt s pluginem do Netbeans 6.0. Včera mi autoři pluginu vysvětlili a dnes jsem si oveřil,...

Solaris

How to find out which process listens on certain port on Solaris?

This week i (again after a while) needed to know which (damn) process heldcertain port and so was quite "successfully" blocking my code.In Tux world i believe problem like this could be solved simply by using a stupidparameter of netstat command. It is unfortunately not that easy on Solaris :-(In an excited mood i totally forgot i had written a handy shell script for thispurpose some time ago. So i killed all suspicious processes to solve the problem.Just to help myself keep in mind there is a better way i published the script at http://blogs.sun.com/japod/resource/portHolder.shThe script exploits pfile command, which provides informationon files being used by certain process. And since everything is a file in the unix world,pfiles provides information on port numbers as well.The bad news is that you need to invoke pfile commandfor every single running process in order to get complete information.Core of the script looks like the following:PIDS=`ps -ef $LIMIT_UID| awk '{ print $2 }' | sed 1d`for p in $PIDS ;do pfiles $p 2> /dev/null | grep "port: $PORTNUM" > /dev/null 2>&1 if test 0 -eq $? ;then if test -z "$PRINT_ARGS" ;then ps -p $p | sed 1d else pargs -l $p fi fi doneLets say, you want to find out who holds port number 1175. Then you run:%portHolder.sh -p 11750 3673 pts/4 0:34 javaWell, you might have launched many java processes, so in order to find out which one is"yours" you add -a parameter:%portHolder.sh -p 11750 -a

This week i (again after a while) needed to know which (damn) process held certain port and so was quite "successfully" blocking my code.In Tux world i believe problem like this could be solved simply...

REST

RESTful Web Services On Glassfish

Recently Jersey module become available on GlassFish Update Center. It comes along with several examples, which use GlassFish as a web container.The examples show how to build RESTful web services using Java.If you want to see such web services in action and find out how to implement them, the fastest way is probably todownload and install GlassFishinstall Jersey module from GlassFish Update CenterTry out the examples bundled with JerseyThis entry will introduce one of the examples and I plan to write about the others in blog entries to come.Bookstore exampleAfter installing Jersey module, the Bookstore example should be available at $AS_HOME/jersey/examples/Bookstore directory.To run the example you can do the following:Change dir:% cd $AS_HOME/jersey/examples/BookstoreBuild the example by running ant bundled within GlassFish:% $AS_HOME/lib/ant/bin/antStart default GlassFish domain via command line interface.% $AS_HOME/bin/asadmin start-domainDeploy the sample:% $AS_HOME/bin/asadmin deploy dist/Bookstore.warThe whole example consists of a bookstore with CDs and books. CDs have tracks associated with them. To model the bookstore in RESTful world, the example introduces bookstore, CD, book and track resources.Mapping of URIs to individual resources is shown in the following table: URI pathResource classHTTP methods/BookstoreGET/countBookstore GET/timeBookstoreGET/items/{itemid}Book, CDGET/items/{itemid}/tracks/{num}TrackGETSo if you open your web browser and navigate to http://localhost:8080/Bookstore,you should see something like this:which is a HTML representation of the bookstore resource.It provides links to it's contents, so you can also ask for (and HTTP GET:-) representationsof a particular CD item and one of it's tracks:Bookstore example provides only read-only access to it's resources but it gives you a very good chance to seehow to implement container-containee relationshipand how to use JSP views for your resource representationsJersey module comes along with source code, so there is nothing to prevent you from playing and experimenting with the Bookstore example.

Recently Jersey module become available on GlassFish Update Center. It comes along with several examples, which use GlassFish as a web container.The examples show how to build RESTful web services...

REST

JSON Representation of JAXB Object Sample

The example is available at http://mediacast.sun.com/share/japod/JsonFromJaxb.zipI have bundled all necessary jar files, so everything you need to run the exampleis to unzip the archive, cd to JsonFromJaxb and run % ant distIt will produce dist/JsonFromJaxb.war, which you can deploy to your favorite Java web container.My favorite container is GlassFish, so I would continue with% $AS_HOME/bin/asadmin deploy dist/JsonFromJaxb.warThe flights resource should be then available at something likehttp://localhost:8080/JsonFromJaxb/flightsdepending on your web container configuration.Please see how it works for me at the following screenshot:If you want (i.e. you set Accept HTTP header to "application/xml") to get XML representation, you will GET this:<flights> <flight flightId="OK123"> <company>Czech Airlines</company> <number>123</number> <aircraft>B737</aircraft> </flight> <flight flightId="OK124"> <company>Czech Airlines</company> <number>124</number> <aircraft>AB115</aircraft> </flight></flights>If you want JSON, the following is what you will GET:{"flights":{"flight":[{"@flightId":"OK123","company":{"$":"Czech Airlines"},"number":{"$":"123"},"aircraft":{"$":"B737"}},{"@flightId":"OK124","company":{"$":"Czech Airlines"},"number":{"$":"124"},"aircraft":{"$":"AB115"}}]}}The example contains Netbeans project files,so you might want to open it in the NB IDE. If you want to see the most importantpart of the source code, just look at src/java/com/sun/ws/rest/samples/jsonfromjaxb/resources/FlightList.java.You can see what is inside bellow. Please note, that you can not only GET the JSON representation,but also PUT a new one. @UriTemplate(value = "/flights/")public class FlightList { static Flights myFlights; public FlightList() { } @HttpMethod(value = "GET") @ProduceMime({"application/json", "application/xml"}) public Flights getFlightList() { return getFlights(); } @HttpMethod(value = "PUT") @ConsumeMime({"application/json", "application/xml"}) public Response putFlightListAsJson(Flights flights) { Response.Builder rBuilder = Response.Builder.noContent(); setFlights(flights); return rBuilder.build(); } private synchronized void setFlights(Flights flights) { myFlights = flights; } private synchronized Flights getFlights() { if (null == myFlights) { myFlights = (new ObjectFactory()).createFlights(); FlightType fligth123 = new FlightType(); fligth123.setCompany("Czech Airlines"); fligth123.setNumber(123); fligth123.setFlightId("OK123"); fligth123.setAircraft("B737"); FlightType fligth124 = new FlightType(); fligth124.setCompany("Czech Airlines"); fligth124.setNumber(124); fligth124.setFlightId("OK124"); fligth124.setAircraft("AB115"); myFlights.getFlight().add(fligth123); myFlights.getFlight().add(fligth124); } return myFlights; }}

The example is available at http://mediacast.sun.com/share/japod/JsonFromJaxb.zip I have bundled all necessary jar files, so everything you need to run the exampleis to unzip the archive, cd to...

REST

JSON Entity Providers In Jersey

I have recently added support for JSON entity providers to Jersey. Here you can find a simple sample showing how to utilize them. The entity providers follow a general schema described by Paul.The following resource class will publish CZK exchange rates for EUR and USD. Data willbe provided in JSON format.@UriTemplate("/rates")public class ExchangeRates { @ProduceMime("application/json") @UriTemplate("CZK") public JSONObject getRates() { try { return new JSONObject() .put("EUR", 28.08) .put("USD", 20.04); } catch (JSONException ex) { throw new WebApplicationException(ex); } }}After deploying the resource and sending a GET request to http://<host>:<port>/rates/CZKthe following data will be provided to you:{"EUR":28.08,"USD":20.04}You might of course want to cover multiple currencies.Following sample code shows how to achieve it.@UriTemplate("/rates")public class HelloWorldResource { @HttpMethod("GET") @ProduceMime("application/json") @UriTemplate("{currency}") public JSONObject getRates(@UriParam("currency") String currency) { if ("CZK".equals(currency)) { try { return new JSONObject() .put("EUR", 28.08) .put("USD", 20.04); } catch (JSONException ex) { throw new WebApplicationException(ex); } } else throw new NotFoundException("Unknown currency " + currency); }}This way you do not need to hardcode specific currency to the URI template.In a real web service you would probably return data taken from a database.However the samples shown the way to use JSON format for data transport froma Jersey based web service to it's client.

I have recently added support for JSON entity providers to Jersey. Here you can find a simple sample showing how to utilize them. The entity providers follow a general schema described by Paul.The...

WS-Policy

Using External Policies

In Manual Web Service Configuration In From Java Case you saw how to manually configure Java web service endpoint. This entry describes how to use external policies for endpoint configuration instead of including policy assertions directly into WSIT config file. The scenario enables you to store and maintain all your policies at one central place...PreparationTo be able to reproduce following steps you will need an installation of glassfish v2. (I was using gf v2 b46)I presume, your GlassFish instance is running and has $AS_HOME base directory.Step 1. Create And Publish Your "Policy Repository"The easiest way how to do that is to publish them as a static XML file:$ vim $AS_HOME/domains/domain1/docroot/policies.xmlContent of your newly created "policy repository" could be as follows:<?xml version="1.0" encoding="UTF-8"?><policies xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsaws="http://www.w3.org/2006/05/addressing/wsdl" xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm/policy"> <wsp:Policy wsu:Id="Class1BindingPolicy"> <wsp:ExactlyOne> <wsp:All> <wsrm:RMAssertion/> <wsaws:UsingAddressing/> </wsp:All> </wsp:ExactlyOne> </wsp:Policy></policies>This way your "policy repository" should be available at http://localhost:8080/policies.xml and you have defined just one policy Class1BindingPolicy which could be referenced as http://localhost:8080/policies.xml#Class1BindingPolicyStep 2. Create Your EndpointThe endpoint is created the same way as in Manual Web Service Configuration In From Java CaseFor sake of clarity I will repeat the steps here:Creating the endpoint implementation class:$ mkdir work-wspol ; cd work-wspol ; vim Stock.javapackage org.example;import javax.jws.WebMethod;import javax.jws.WebService;@WebService(serviceName="StockSvc", portName="StockPort", targetNamespace="http://example.org")public class Stock { @WebMethod() public boolean itemAvaiable (String itemId, int amount) { return Math.random() > 0.6; }}Compiling it:$ mkdir -p WEB-INF/classes; javac -cp $AS_HOME/lib/javaee.jar -d WEB-INF/classes Stock.javaAnd creating a wsit config file skeleton:$ $AS_HOME/bin/wsgen -wsdl -cp WEB-INF/classes org.example.Stock ; mv StockSvc.wsdl WEB-INF/wsit-org.example.Stock.xmlNow remove useless lines from the skeleton:$ vim WEB-INF/wsit-org.example.Stock.xmlLines to remove: <types> <xsd:schema> <xsd:import namespace="http://example.org" schemaLocation="StockSvc_schema1.xsd"/> </xsd:schema> </types>And:<soap:address location="REPLACE_WITH_ACTUAL_URL"/>Step 3. Attach The External PolicyAttaching an external policy simply means adding a PolicyReference to the config file.In our case, we will only add the following line to our wsit config file:<wsp:PolicyReference xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" URI="http://localhost:8080/policies.xml#Class1BindingPolicy"/>So that our config file will look like:<?xml version="1.0" encoding="UTF-8" standalone="yes"?><definitions targetNamespace="http://example.org" name="StockSvc" xmlns:tns="http://example.org" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"xmlns="http://schemas.xmlsoap.org/wsdl/"> <message name="itemAvaiable"> <part name="parameters" element="tns:itemAvaiable"/> </message> <message name="itemAvaiableResponse"> <part name="parameters" element="tns:itemAvaiableResponse"/> </message> <portType name="Stock"> <operation name="itemAvaiable"> <input message="tns:itemAvaiable"/> <output message="tns:itemAvaiableResponse"/> </operation> </portType> <binding name="StockPortBinding" type="tns:Stock"><wsp:PolicyReference xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" URI="http://localhost:8080/policies.xml#Class1BindingPolicy"/> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/> <operation name="itemAvaiable"> <soap:operation soapAction=""/> <input> <soap:body use="literal"/> </input> <output> <soap:body use="literal"/> </output> </operation> </binding> <service name="StockSvc"> <port name="StockPort" binding="tns:StockPortBinding"> </port> </service></definitions>Step 4. Deploying The Newly Created And Configured EndpointYou should now be able to deploy the endpoint in one shot by:$ jar cvf $AS_HOME/domains/domain1/autodeploy/stock.war WEB-INFCloser ViewIf you look at the published WSDL of our endpoint, you will probably notice thatoriginal external reference was replaced by a local one and the policy definition was included into the wsdl.It means that consumer of your endpoint does not need to have access to original "policy repository". On the other hand, if you forbid access to your "policy repository" from outside, described mechanism will still work! So what? You can store sensitive information in your policy repository (keystore locations, passwords, etc.). Such information will be properly used for configuring your endpoints and safely removed from published WSDLs. It means you can maintain such a sensitive information at just one place and still be able to use it for configuring lots of your endpoints.

In Manual Web Service Configuration In From Java Case you saw how to manually configure Java web service endpoint. This entry describes how to use external policies for endpoint...

WS-Policy

Manual Web Service Configuration In From Java Case

As Fabian mentioned in his recent blog entry (http://blogs.sun.com/ritzmann), attaching policy assertionsto webservices created from wsdl could be simply done by inserting the assertions directly into appropriate wsdl document. Today I will show how to attach them in from Java casePreparationAll you will need is JDK (http://java.sun.com/javase/downloads/index.jsp)and Java EE Application Server with integrated WSIT. What follows was tested withjdk 5.0 update 10 (http://java.sun.com/javase/downloads/index_jdk5.jsp)glassfish v2 build 33 (https://glassfish.dev.java.net/public/downloadsindex.html)wsit built from sources (https://wsit.dev.java.net/ )on solaris (http://www.opensolaris.org/) ;-)Step 1. Write a Simple Web ServiceI will start with a new empty working directory and create a simple java class as follows:$ mkdir work-wspol ; cd work-wspol ; vim Stock.javapackage org.example;import javax.jws.WebMethod;import javax.jws.WebService;@WebService(serviceName="StockSvc", portName="StockPort", targetNamespace="http://example.org")public class Stock { @WebMethod() public boolean itemAvaiable (String itemId, int amount) { return Math.random() > 0.6; }}Step 2. Deploy the Service To Make Sure "It Works"Prepare skeleton for a war archive to deploy:$ mkdir -p WEB-INF/classesAnd compile the web service, your AS_HOME variable must point to glassfish installation/home directory:$ javac -cp $AS_HOME/lib/javaee.jar -d WEB-INF/classes Stock.javaThen you can bundle and deploy the service in one shot:$ jar cvf $AS_HOME/domains/domain1/autodeploy/stock.war WEB-INFPlease note that for sake of clarity we have bundled only really necessary files into our war archive. For this sample it should work all right thoughAfter a minute (presuming your glassfish instance is running), you should be able to see the new web service wsdl displaying at http://localhost:8080/stock/StockSvc?wsdlStep 3. Create WSIT Config File SkeletonConfig file uses the same format as the wsdl. We only need a skeleton -- something which matches our service.The easiest way to obtain it is to use the one from http://localhost:8080/stock/StockSvc?wsdl.Another way is to use:$ $AS_HOME/bin/wsgen -wsdl -cp WEB-INF/classes org.example.Stock which should create StockSvc.wsdl file in your work directory.I will use the latter and copy it to my "war space":$ mv StockSvc.wsdl WEB-INF/wsit-org.example.Stock.xmlPlease note the config file filename. It follows general naming convention wsit-<svcClassName>.xml and is placed in WEB-INF directory.To get rid of certain unnecessary dependencies I remove following parts of the config file.$ vim WEB-INF/wsit-org.example.Stock.xml <types> <xsd:schema> <xsd:import namespace="http://example.org" schemaLocation="StockSvc_schema1.xsd"/> </xsd:schema> </types><soap:address location="REPLACE_WITH_ACTUAL_URL"/>I am now ready to attach appropriate policy assertions into the config file.Step 4. Attach Policy AssertionsFor this blog I selected RM policy assertions to be attached to our config file.Appropriate added text is red.<?xml version="1.0" encoding="UTF-8" standalone="yes"?><definitions targetNamespace="http://example.org" name="StockSvc" xmlns:tns="http://example.org" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns="http://schemas.xmlsoap.org/wsdl/"xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm/policy" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"> <message name="itemAvaiable"> <part name="parameters" element="tns:itemAvaiable"/> </message> <message name="itemAvaiableResponse"> <part name="parameters" element="tns:itemAvaiableResponse"/> </message> <portType name="Stock"> <operation name="itemAvaiable"> <input message="tns:itemAvaiable"/> <output message="tns:itemAvaiableResponse"/> </operation> </portType><binding name="StockPortBinding" type="tns:Stock"> <wsp:Policy> <wsp:ExactlyOne> <wsp:All> <wsaw:UsingAddressing/> <wsrm:RMAssertion/> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/> <operation name="itemAvaiable"> <soap:operation soapAction=""/> <input> <soap:body use="literal"/> </input> <output> <soap:body use="literal"/> </output> </operation> </binding> <service name="StockSvc"> <port name="StockPort" binding="tns:StockPortBinding"> </port> </service></definitions>Step 5. Redeploy The ServiceNow we can redeploy the service. We have to undeploy it first by$ rm $AS_HOME/domains/domain1/autodeploy/stock.warAnd deploy it once again, this time with RM switched on:$ jar cvf $AS_HOME/domains/domain1/autodeploy/stock.war WEB-INF

As Fabian mentioned in his recent blog entry (http://blogs.sun.com/ritzmann), attaching policy assertionsto webservices created from wsdl could be simply done by inserting the assertions directly into...

Java

Using JSR-88 For Web Application Deployment in Glassfish

JSR-88 introduces unified J2EE API for deployment. You will see how to use it for deploying/undeploying web applications and it will be demonstrated using glassfishWithout JSR-88You have several options how to deploy a web application onto glassfish.CLI interface ($GLASSFISH_HOME/bin/asadmin command)Admin Console (http://localhost:4848/)Autodeployment (place the war directly into filesystem: $GLASSFISH_HOME/domains/domain1/autodeploy)So for e.g. using CLI interface you can deploy a war file by:$AS_HOME/bin/asadmin deploy testApp.warAnd undeploy it by:$AS_HOME/bin/asadmin undeploy testAppLeveraging JSR-88Yet another option is to use JSR-88 (http://www.jcp.org/en/jsr/detail?id=88) interface.Please download a simple sample from http://blogs.sun.com/japod/resource/wardepl-jsr88.tar.gzwhich depicts how it works.After downloading, you can (presuming your glassfish is installed under $AS_HOME and your default domain instance is up and running):unpack the sample:$ gzip -dc wardepl-jsr88.tar.gz | tar xvf -x ., 0 bytes, 0 tape blocksx ./wardeployment, 0 bytes, 0 tape blocksx ./wardeployment/Main.java, 8044 bytes, 16 tape blocksx ./wardeployment.properties, 168 bytes, 1 tape blocksx ./testApp.war, 3073 bytes, 7 tape blockscompile it:$ javac -cp $AS_HOME/lib/javaee.jar wardeployment/Main.javadeploy attached testAppl.war:$ java -cp .:$AS_HOME/lib/javaee.jar:$AS_HOME/lib/appserv-ext.jar:$AS_HOME/lib/appserv-deployment-client.jar wardeployment.Main deploy testApp.war Deploying app...deployment started : 0%deployment finished : 100%Deploying application in domain completed successfullyTrying to create reference for application in target server completed successfullyTrying to start application in target server completed successfullyDeployment of application testApp completed successfullyEnable of testApp in target server completed successfullyEnable of application in all targets completed successfullyAll operations completed successfullyand undeploy it again:$ java -cp .:$AS_HOME/lib/javaee.jar:$AS_HOME/lib/appserv-ext.jar:$AS_HOME/lib/appserv-deployment-client.jar wardeployment.Main undeploy testAppUndeploying app...While undeploying, trying to stop application in target server completed successfullyWhile undeploying, trying to remove reference for application in target server completed successfullyUndeploying the application Trying to undeploy application from domain completed successfullyUndeployment of application testApp completed successfullyAll operations completed successfully Please note attached wardeployment.properties file, which contains settings for glassfish:jsr88.dm.id=deployer:Sun:AppServer::localhost:4848jsr88.dm.user=adminjsr88.dm.passwd=adminadminjsr88.df.classname=com.sun.enterprise.deployapi.SunDeploymentFactoryThe classname above was taken from $AS_HOME/lib/deployment/sun-as-jsr88-dm.jar:META-INF/MANIFEST.MF file,where you can find it as J2EE-DeploymentFactory-Implementation-Class in accord with JSR-88.The settings are then used to obtain appropriate deployment manager: DeploymentFactoryManager dfm = DeploymentFactoryManager.getInstance(); try { Class dfClass = Class.forName(getParam("jsr88.df.classname")); DeploymentFactory dfInstance; dfInstance = (DeploymentFactory) dfClass.newInstance(); dfm.registerDeploymentFactory(dfInstance); } catch (ClassNotFoundException ex) { ex.printStackTrace(); } catch (IllegalAccessException ex) { ex.printStackTrace(); } catch (InstantiationException ex) { ex.printStackTrace(); } try { deploymentManager = dfm.getDeploymentManager( getParam("jsr88.dm.id"),getParam("jsr88.dm.user"),getParam("jsr88.dm.passwd")); } catch (DeploymentManagerCreationException ex) { ex.printStackTrace(); }For deploying the application, distribute method is then invoked: ProgressObject deplProgress = getDeploymentManager().distribute(getDeploymentManager().getTargets(), new File(warFilename), null);Similarly, deploymentManager is used also for appl undeployment: ProgressObject startProgress = getDeploymentManager().undeploy(myIDs);Please note the calls are asynchronous and you have to wait till the deployment/undeployment finishes.Whole source code of the sample please see bellow:package wardeployment;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.util.Properties;import javax.enterprise.deploy.shared.ModuleType;import javax.enterprise.deploy.shared.factories.DeploymentFactoryManager;import javax.enterprise.deploy.spi.DeploymentManager;import javax.enterprise.deploy.spi.TargetModuleID;import javax.enterprise.deploy.spi.exceptions.DeploymentManagerCreationException;import javax.enterprise.deploy.spi.exceptions.TargetException;import javax.enterprise.deploy.spi.factories.DeploymentFactory;import javax.enterprise.deploy.spi.status.ProgressEvent;import javax.enterprise.deploy.spi.status.ProgressListener;import javax.enterprise.deploy.spi.status.ProgressObject;/\*\* \* \* @author Jakub Podlesak (japod at sun.com) \*/public class Main { class DeploymentListener implements ProgressListener { Main driver; String warContext; DeploymentListener(Main driver, String warContext) { this.driver = driver; this.warContext = warContext; } public void handleProgressEvent(ProgressEvent event) { System.out.println(event.getDeploymentStatus().getMessage()); if (event.getDeploymentStatus().isCompleted()) { try { TargetModuleID[] ids = getDeploymentManager().getNonRunningModules(ModuleType.WAR, getDeploymentManager().getTargets()); TargetModuleID[] myIDs = new TargetModuleID[1]; for (TargetModuleID id : ids) { if (warContext.equals(id.getModuleID())) { myIDs[0] = id; ProgressObject startProgress = driver.getDeploymentManager().start(myIDs); startProgress.addProgressListener(new ProgressListener() { public void handleProgressEvent(ProgressEvent event) { System.out.println(event.getDeploymentStatus().getMessage()); if (event.getDeploymentStatus().isCompleted()) { driver.setAppStarted(true); } } }); } } } catch (IllegalStateException ex) { ex.printStackTrace(); } catch (TargetException ex) { ex.printStackTrace(); } } } } DeploymentManager deploymentManager; boolean appStarted; boolean appUndeployed; String warContext; String warFilename; String wsdlUrl; synchronized void setAppStarted(boolean appStarted) { this.appStarted = appStarted; notifyAll(); } synchronized void setAppUndeployed(boolean appUndeployed) { this.appUndeployed = appUndeployed; notifyAll(); } private String getParam(String param) { return (null == deploymentProperties) ? null : deploymentProperties.getProperty(param); } public DeploymentManager getDeploymentManager() { if (null == deploymentManager) { DeploymentFactoryManager dfm = DeploymentFactoryManager.getInstance(); try { Class dfClass = Class.forName(getParam("jsr88.df.classname")); DeploymentFactory dfInstance; dfInstance = (DeploymentFactory) dfClass.newInstance(); dfm.registerDeploymentFactory(dfInstance); } catch (ClassNotFoundException ex) { ex.printStackTrace(); } catch (IllegalAccessException ex) { ex.printStackTrace(); } catch (InstantiationException ex) { ex.printStackTrace(); } try { deploymentManager = dfm.getDeploymentManager( getParam("jsr88.dm.id"),getParam("jsr88.dm.user"),getParam("jsr88.dm.passwd")); } catch (DeploymentManagerCreationException ex) { ex.printStackTrace(); } } return deploymentManager; } void runApp(String warFilename, String warContext) { setAppStarted(false); ProgressObject deplProgress = getDeploymentManager().distribute(getDeploymentManager().getTargets(), new File(warFilename), null); deplProgress.addProgressListener(new DeploymentListener(this, warContext)); waitForAppStart(); } void undeployApp(String warContext) { setAppUndeployed(false); try { TargetModuleID[] ids = getDeploymentManager().getRunningModules(ModuleType.WAR, getDeploymentManager().getTargets()); TargetModuleID[] myIDs = new TargetModuleID[1]; for (TargetModuleID id : ids) { if (warContext.equals(id.getModuleID())) { myIDs[0] = id; ProgressObject startProgress = getDeploymentManager().undeploy(myIDs); startProgress.addProgressListener(new ProgressListener() { public void handleProgressEvent(ProgressEvent event) { System.out.println(event.getDeploymentStatus().getMessage()); if (event.getDeploymentStatus().isCompleted()) { setAppUndeployed(true); } } }); } } } catch (IllegalStateException ex) { ex.printStackTrace(); } catch (TargetException ex) { ex.printStackTrace(); } waitForAppUndeployment(); } void releaseDeploymentManager() { if (null != deploymentManager) { deploymentManager.release(); } } synchronized void waitForAppStart() { while(!appStarted) { try { wait(); } catch (InterruptedException e) {} } } synchronized void waitForAppUndeployment() { while(!appUndeployed) { try { wait(); } catch (InterruptedException e) {} } } /\*\* Creates a new instance of Main \*/ public Main() { } public Main(String filename) { setProperties(filename); } private final static String SyntaxHelp = "syntax:\\n\\tdeploy \\n\\tundeploy "; private final static String PropertiesFilename = "wardeployment.properties"; private Properties deploymentProperties; private void setProperties(String filename) { FileInputStream fis = null; try { fis = new FileInputStream(filename); deploymentProperties = new Properties(); deploymentProperties.load(fis); fis.close(); } catch (FileNotFoundException ex) { ex.printStackTrace(); } catch (IOException ex) { ex.printStackTrace(); } } private static void printHelpAndExit() { System.out.println(SyntaxHelp); System.exit(1); } /\*\* \* @param args the command line arguments \*/ public static void main(String[] args) { if (args.length < 1) { printHelpAndExit(); } Main worker = new Main(PropertiesFilename); if ("deploy".equals(args[0])) { System.out.println("Deploying app..."); worker.runApp(args[1], args[1].substring(0,args[1].length()-4)); worker.releaseDeploymentManager(); } else if ("undeploy".equals(args[0])) { System.out.println("Undeploying app..."); worker.undeployApp(args[1]); worker.releaseDeploymentManager(); } }}Further InfoPlease visit https://glassfish.dev.java.net/javaee5/deployment/ to get a lot more information on the topic.

JSR-88 introduces unified J2EE API for deployment. You will see how to use it for deploying/undeploying web applications and it will be demonstrated using glassfish Without JSR-88 You have several...

WS-Policy

Finding Code Generating Log Messages By Ids In WSIT WS-Policy Framework

Recently I got an e-mail containing following log message id: SEVERE: WSP001002:Message was generated by our class in com.sun.xml.ws.policy.jaxws package.In the first place I was wondering where in the code the message had been logged:$ grep -n WSP001002 wsit/rt/src/\*\*/\*.javaIt returned empty result, even if I was sure such an id was used in the code.And the reason?In policy code we used a convention that log messages starting with WSP<id number> were generated with message with keys starting with WSP_<id number>. We place an underscore between WSP and the number of the message.And indeed, after trying:$ grep -n WSP_001002 wsit/rt/src/\*\*/\*.javaI gotwsit/rt/src/com/sun/xml/ws/policy/jaxws/PolicyConfigParser.java:278: LOGGER.severe("parseModel", LocalizationMessages.WSP_001002_WSDL_IMPORT_FAILED(), ex);wsit/rt/src/com/sun/xml/ws/policy/jaxws/PolicyConfigParser.java:279: throw new PolicyException(LocalizationMessages.WSP_001002_WSDL_IMPORT_FAILED(), ex);wsit/rt/src/com/sun/xml/ws/policy/jaxws/PolicyConfigParser.java:281: LOGGER.severe("parseModel", LocalizationMessages.WSP_001002_WSDL_IMPORT_FAILED(), ex);wsit/rt/src/com/sun/xml/ws/policy/jaxws/PolicyConfigParser.java:282: throw new PolicyException(LocalizationMessages.WSP_001002_WSDL_IMPORT_FAILED(), ex);wsit/rt/src/com/sun/xml/ws/policy/jaxws/PolicyConfigParser.java:284: LOGGER.severe("parseModel", LocalizationMessages.WSP_001002_WSDL_IMPORT_FAILED(), ex);wsit/rt/src/com/sun/xml/ws/policy/jaxws/PolicyConfigParser.java:285: throw new PolicyException(LocalizationMessages.WSP_001002_WSDL_IMPORT_FAILED(), ex);

Recently I got an e-mail containing following log message id: SEVERE: WSP001002: Message was generated by our class in com.sun.xml.ws.policy.jaxws package.In the first place I was wondering where in...

WS-Policy

Measuring Performance of Policy Code in WSIT -- First Steps

This week I have spent some time on measuring performance of our wspolicy implementationand it's impact on overall performance of WSIT (http://wsit.dev.java.net/).Nowadays -- after feature freeze -- we want to spend some cycles on performance improvements.In this blog you can find some initial figures before performance optimization.First attemptFor the initial measurement I created two services. Exactly same services just with one difference.One configured using policies, one without any policy attached to it.The wsdl file for the first one follows:<?xml version="1.0"?><definitions xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://me.org/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://me.org/" name="SillyServiceService"> <wsp:UsingPolicy/> <wsp:Policy xmlns:ns1="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" ns1:Id="SillyServicePortBindingPolicy"> <wsp:ExactlyOne> <wsp:All> <ns7:OptimizedMimeSerialization xmlns:ns7="http://schemas.xmlsoap.org/ws/2004/09/policy/optimizedmimeserialization"/> <ns8:RMAssertion xmlns:ns8="http://schemas.xmlsoap.org/ws/2005/02/rm/policy"> <ns8:InactivityTimeout Milliseconds="600000"/> </ns8:RMAssertion> <ns9:SupportingTokens xmlns:ns9="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <wsp:Policy> <wsp:ExactlyOne> <wsp:All> <ns9:X509Token ns9:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient"> <wsp:Policy> <wsp:ExactlyOne> <wsp:All> <ns9:RequireThumbprintReference/> <ns9:WssX509V3Token11/> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> </ns9:X509Token> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> </ns9:SupportingTokens> <ns10:SymmetricBinding xmlns:ns10="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <wsp:Policy> <wsp:ExactlyOne> <wsp:All> <ns10:AlgorithmSuite> <wsp:Policy> <wsp:ExactlyOne> <wsp:All> <ns10:Basic128/> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> </ns10:AlgorithmSuite> <ns10:IncludeTimestamp/> <ns10:Layout> <wsp:Policy> <wsp:ExactlyOne> <wsp:All> <ns10:Strict/> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> </ns10:Layout> <ns10:OnlySignEntireHeadersAndBody/> <ns10:ProtectionToken> <wsp:Policy> <wsp:ExactlyOne> <wsp:All> <ns10:X509Token ns10:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient"> <wsp:Policy> <wsp:ExactlyOne> <wsp:All> <ns10:RequireDerivedKeys/> <ns10:WssX509V3Token11/> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> </ns10:X509Token> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> </ns10:ProtectionToken> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> </ns10:SymmetricBinding> <ns11:Trust10 xmlns:ns11="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <wsp:Policy> <wsp:ExactlyOne> <wsp:All> <ns11:MustSupportIssuedTokens/> <ns11:RequireClientEntropy/> <ns11:RequireServerEntropy/> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> </ns11:Trust10> <ns12:Wss10 xmlns:ns12="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <wsp:Policy> <wsp:ExactlyOne> <wsp:All> <ns12:MustSupportRefIssuerSerial/> <ns12:MustSupportRefKeyIdentifier/> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> </ns12:Wss10> <ns13:Ordered xmlns:ns13="http://sun.com/2006/03/rm"/> <ns14:UsingAddressing xmlns:ns14="http://www.w3.org/2006/05/addressing/wsdl"/> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> <wsp:Policy xmlns:ns15="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" ns15:Id="SillyServicePortBinding_sayHelloInput_Policy"> <wsp:ExactlyOne> <wsp:All> <ns16:EncryptedElements xmlns:ns16="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"/> <ns17:EncryptedParts xmlns:ns17="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <ns17:Body/> </ns17:EncryptedParts> <ns18:SignedElements xmlns:ns18="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"/> <ns19:SignedParts xmlns:ns19="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <ns19:Body/> </ns19:SignedParts> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> <wsp:Policy xmlns:ns20="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" ns20:Id="SillyServicePortBinding_sayHelloOutput_Policy"> <wsp:ExactlyOne> <wsp:All> <ns21:EncryptedElements xmlns:ns21="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"/> <ns22:EncryptedParts xmlns:ns22="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <ns22:Body/> </ns22:EncryptedParts> <ns23:SignedElements xmlns:ns23="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"/> <ns24:SignedParts xmlns:ns24="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <ns24:Body/> </ns24:SignedParts> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> <types> <xsd:schema> <xsd:import namespace="http://me.org/" schemaLocation="http://localhost:8080/withPolicies/SillyServiceService?xsd=1"/> </xsd:schema> </types> <message name="sayHello"> <wsp:PolicyReference URI="#SillyServicePortBindingPolicy"/> <part name="parameters" element="tns:sayHello"/> </message> <message name="sayHelloResponse"> <part name="parameters" element="tns:sayHelloResponse"/> </message> <portType name="SillyService"> <operation name="sayHello"> <input message="tns:sayHello"/> <output message="tns:sayHelloResponse"/> </operation> </portType> <binding name="SillyPortBinding" type="tns:SillyService"> <wsp:PolicyReference URI="#SillyServicePortBindingPolicy"/> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/> <operation name="sayHello"> <wsp:PolicyReference URI="#SillyServicePortBinding_sayHelloInput_Policy"/> <wsp:PolicyReference URI="#SillyServicePortBinding_sayHelloOutput_Policy"/> <soap:operation soapAction=""/> <input> <wsp:PolicyReference URI="#SillyServicePortBinding_sayHelloInput_Policy"/> <wsp:PolicyReference URI="#SillyServicePortBinding_sayHelloOutput_Policy"/> <soap:body use="literal"/> </input> <output> <wsp:PolicyReference URI="#SillyServicePortBinding_sayHelloInput_Policy"/> <wsp:PolicyReference URI="#SillyServicePortBinding_sayHelloOutput_Policy"/> <soap:body use="literal"/> </output> </operation> </binding> <service name="SillyServiceService"> <port name="SillyPort" binding="tns:SillyPortBinding"> <wsp:PolicyReference URI="#SillyServicePortBindingPolicy"/> <soap:address location="http://localhost:8080/withPolicies/SillyServiceService"/> </port> </service></definitions>And the same wsdl without policies (for the second service):<?xml version="1.0"?><definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://me.org/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://me.org/" name="SillyServiceService"> <types> <xsd:schema> <xsd:import namespace="http://me.org/" schemaLocation="http://localhost:8080/withoutPolicies/SillyServiceService?xsd=1"/> </xsd:schema> </types> <message name="sayHello"> <part name="parameters" element="tns:sayHello"/> </message> <message name="sayHelloResponse"> <part name="parameters" element="tns:sayHelloResponse"/> </message> <portType name="SillyService"> <operation name="sayHello"> <input message="tns:sayHello"/> <output message="tns:sayHelloResponse"/> </operation> </portType> <binding name="SillyPortBinding" type="tns:SillyService"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/> <operation name="sayHello"> <soap:operation soapAction=""/> <input> <soap:body use="literal"/> </input> <output> <soap:body use="literal"/> </output> </operation> </binding> <service name="SillyServiceService"> <port name="SillyPort" binding="tns:SillyPortBinding"> <soap:address location="http://localhost:8080/withoutPolicies/SillyServiceService"/> </port> </service></definitions>Please note, that size of the wsdl files differs a bit.I was curious, what would happen if I measured time for obtainingthe wsdl docs via get method from published endpoints:http://localhost:8080/withoutPolicies/SillyServiceService?wsdlhttp://localhost:8080/withPolicies/SillyServiceService?wsdlFor more information I also bundled wsdl docs as a static content to deployed warsand included them into measurements.http://localhost:8080/withoutPolicies/SillyServiceService.wsdlhttp://localhost:8080/withPolicies/SillyServiceService.wsdlFigures I got from jmeter (http://jakarta.apache.org/jmeter/)you can see bellow:From the figures you can see, that policy processing indeed have an impacton webservice communication performance as clients basically have to read wsdl docsfrom server in order to get policies (i.e. config data) out of it.The numbers show that when policies are used getting the wsdl is more than two times slower,while in terms of throughput it is not that bad.Ok, lets dive deeper with more suitable tool -- NetBeans Profiler (http://www.netbeans.org/products/profiler/) to find out where possible improvements might be done.Figures from NetBeans ProfilerWhat's bellow is just several screenshots and a few comments. I will come back to them in another blog soon.From Java Case (JSR-109 Compliant)Quite good. Policy code needed about 17 % of time when wsdl was generated:Which methods took the time?:Hotspots:From WSDL CaseHere it is worse. Policy processing took about 45 % of wsdl parser time:Let's see which methods did it:And what about hotspots?:

This week I have spent some time on measuring performance of our wspolicy implementation and it's impact on overall performance of WSIT (http://wsit.dev.java.net/).Nowadays -- after feature freeze --...

Oracle

Integrated Cloud Applications & Platform Services