Those of you living in Ireland who tune to listen to a brilliant NewsTalk team will recognize where I've got the idea for this regular, first half of the year, off-topic post :-), indeed, it is from NewsTalk being "more than just news, you know!".
So I got inspired and decided to do this short entry and suggest to you, the developers of web services, that CXF is more just a library,
It is the home, blueprint for developing the modern, secure web service applications.
Thursday, April 4, 2013
On the way to making CXF JAX-RS run easily in your application container
Awhile back I posted an entry on how to get CXF JAX-RS loaded successfully within your favorite Java EE application container, and specifically within the containers like JBoss or Glassfish which have their preferred JAX-RS implementations actively supported.
I think it was a good enough initial step but it proved to be quite incomplete, with users reporting CXF failing to handle the objects of some of JAX-RS core types like Response.
In this rather technical post I will give an update on the situation.
What typically happens is that when Glassfish or JBoss loads a CXF-enabled application, the active subsystem (Jersey or RestEasy based) will still intercept the runtime or application code doing a code like "Response.ok().build()" - this static sequence of calls will end up being processed by this subsystem which leads to a somewhat unusual case, where the CXF runtime ends up processing 'foreign' JAX-RS Response objects - attempting to cast to the CXF-aware Response object breaks the application.
So what we've decided to do now is to start working on making CXF JAX-RS completely isolated from the loaded third-party JAX-RS libraries, by minimizing and when possible completely removing the calls like "Response.fromResponse" which lead to the 3rd party subsystems intercepting the control. This makes CXF JAX-RS more robust when loaded alongside other JAX-RS runtimes, and also marginally faster - the cost of getting from the static code sequence to the actual Response builder implementation capable of producing Response is not completely negligible.
This is not possible to avoid completely - for example, you custom filter, exception mapper or indeed the user code will inevitably create a JAX-RS Response instance which will be 'foreign' to the CXF runtime. In these cases CXF will simply copy such Responses into its own Response implementation.
I hope it will make it very easy eventually to get CXF JAX-RS up and running in the latest JBoss and Glassfish distributions, due to it becoming effectively self-contained. Some more runtime code modifications may prove to be required but IMHO we are on the right path.
It is very well understood that for a given container it makes a lot of sense to optimize around a selected JAX-RS implementation, specifically in case of JBoss and Glassfish we are talking about well-known and recognized implementations.
This effort is all about helping those users who have decided to work with CXF JAX-RS in these containers continue doing so - this is all to it really :-).
I think it was a good enough initial step but it proved to be quite incomplete, with users reporting CXF failing to handle the objects of some of JAX-RS core types like Response.
In this rather technical post I will give an update on the situation.
What typically happens is that when Glassfish or JBoss loads a CXF-enabled application, the active subsystem (Jersey or RestEasy based) will still intercept the runtime or application code doing a code like "Response.ok().build()" - this static sequence of calls will end up being processed by this subsystem which leads to a somewhat unusual case, where the CXF runtime ends up processing 'foreign' JAX-RS Response objects - attempting to cast to the CXF-aware Response object breaks the application.
So what we've decided to do now is to start working on making CXF JAX-RS completely isolated from the loaded third-party JAX-RS libraries, by minimizing and when possible completely removing the calls like "Response.fromResponse" which lead to the 3rd party subsystems intercepting the control. This makes CXF JAX-RS more robust when loaded alongside other JAX-RS runtimes, and also marginally faster - the cost of getting from the static code sequence to the actual Response builder implementation capable of producing Response is not completely negligible.
This is not possible to avoid completely - for example, you custom filter, exception mapper or indeed the user code will inevitably create a JAX-RS Response instance which will be 'foreign' to the CXF runtime. In these cases CXF will simply copy such Responses into its own Response implementation.
I hope it will make it very easy eventually to get CXF JAX-RS up and running in the latest JBoss and Glassfish distributions, due to it becoming effectively self-contained. Some more runtime code modifications may prove to be required but IMHO we are on the right path.
It is very well understood that for a given container it makes a lot of sense to optimize around a selected JAX-RS implementation, specifically in case of JBoss and Glassfish we are talking about well-known and recognized implementations.
This effort is all about helping those users who have decided to work with CXF JAX-RS in these containers continue doing so - this is all to it really :-).
Tuesday, March 5, 2013
Use SAML2 Assertions as OAuth2 Token Grants or Authenticators with CXF
OAuth2 allows third-party clients to use different types of grants in order to request access tokens. The specification defines a number of grant types to get some specific flows supported, but also allows for extensions - one can use whatever custom grant is required in a particular scenario.
SAML2 Bearer Assertion Profiles and JWT Bearer Token Profiles standardize two such extension grants, SAML2 Bearer Assertions and JWT Bearer Tokens grants, which can be used like any other OAuth 2.0 grants in order to request new access tokens. In addition, these documents specify how SAML2 Bearer Assertions and JWT Bearer Tokens can be used as client authentication credentials, irrespectively of the actual token grant type.
The use of SAML2 Bearer Assertions in particular is likely to get more immediate traction given that SAML2 Identity Providers are deployed in many productions, though no doubt JWT is going to be become much more visible going forward.
I think it is fare to say that it is the introduction of SAML2 into an OAuth 2.0 'space' that led some experts to start talking about the increased complexity of OAuth 2.0 compared to OAuth 1.0. One can definitely agree that working with SAML is more complex than with simple tokens.That said it is not a default token type after all - it is really about getting the Identity Providers which are already deployed be 'involved' which is always important - if that is not something that is needed for your case then no SAML2 assertions have to be used at all.
You may want to check SalesForce and PingIdentity documentation for more information on how to get SAML2 assertions utilized with OAuth2 servers.
Apache CXF OAuth2 module introduces an initial support for using SAML2 Bearer Assertions as grants and authenticators. Please check the documentation, see how easy it is to get the client code to use SAML2 assertions, start experimenting with the code and plan moving your OAuth2 project to the next level :-)
SAML2 Bearer Assertion Profiles and JWT Bearer Token Profiles standardize two such extension grants, SAML2 Bearer Assertions and JWT Bearer Tokens grants, which can be used like any other OAuth 2.0 grants in order to request new access tokens. In addition, these documents specify how SAML2 Bearer Assertions and JWT Bearer Tokens can be used as client authentication credentials, irrespectively of the actual token grant type.
The use of SAML2 Bearer Assertions in particular is likely to get more immediate traction given that SAML2 Identity Providers are deployed in many productions, though no doubt JWT is going to be become much more visible going forward.
I think it is fare to say that it is the introduction of SAML2 into an OAuth 2.0 'space' that led some experts to start talking about the increased complexity of OAuth 2.0 compared to OAuth 1.0. One can definitely agree that working with SAML is more complex than with simple tokens.That said it is not a default token type after all - it is really about getting the Identity Providers which are already deployed be 'involved' which is always important - if that is not something that is needed for your case then no SAML2 assertions have to be used at all.
You may want to check SalesForce and PingIdentity documentation for more information on how to get SAML2 assertions utilized with OAuth2 servers.
Apache CXF OAuth2 module introduces an initial support for using SAML2 Bearer Assertions as grants and authenticators. Please check the documentation, see how easy it is to get the client code to use SAML2 assertions, start experimenting with the code and plan moving your OAuth2 project to the next level :-)
Monday, February 18, 2013
FIQL explained in JAX Magazine tutorial
JAX magazine for Java developers features articles and tutorials which can help to get the most of all the new and cool technologies and developments happening in the Java land today.
The latest issue offers, among other features, the tutorial introducing Feed Item Query Language (FIQL) and how it is currently supported in Apache CXF. Please download the issue as a PDF or get it over your preferred channel (on iTunes, etc), and see what you can do with FIQL - and provide the valuable feedback.
Enjoy!
The latest issue offers, among other features, the tutorial introducing Feed Item Query Language (FIQL) and how it is currently supported in Apache CXF. Please download the issue as a PDF or get it over your preferred channel (on iTunes, etc), and see what you can do with FIQL - and provide the valuable feedback.
Enjoy!
Tuesday, January 29, 2013
Jettison 1.3.3 is out
Jettison 1.3.3 has been released earlier this month, please check the Download page.
This release ships a better MappedXMLStreamReader: arrays to be mapped to primitive collections in JAXB beans can be correctly processed without the loss of the data, some if its methods dealing with text will work properly as expected and the callers can identify an absolute position of the first illegal JSON character after XMLStreamException has been thrown.
As usual, I'd like to thank the users who have reported the issues against Jettison and would like to encourage to get the patches provided.
I think over the time it has become clearer to me why Jettison is still being used, at least by some of CXF users, even though such powerful and popular processors as Jackson exist. Jettison is a very lightweight library, it has just few basic STAX XMLStreamReader and XMLStreamWriter implementations: this alone is not sufficient to produce a perfect JSON. But in CXF at least Jettison can be customized a lot to make it produce if not perfect but close enough JSON sequences.
This is what keeps it visible really in CXF land at least IMHO - the fact that the users can use it to write or read simple sequences (with many JSON consumers actually expecting simple enough sequences) but also nearly completely control the way a given sequence is produced or consumed. For example, people are talking about backward and forward compatibility with respect to processing XML - same can be achieved for JSON in CXF, all without code-related changes.
This is where its niche is, a bridge between JAXB and JSON, simple to medium complexity sequences, the possibility of the easy enough customization.
If you work with Jettison: please test the latest release and provide the feedback, thanks
This release ships a better MappedXMLStreamReader: arrays to be mapped to primitive collections in JAXB beans can be correctly processed without the loss of the data, some if its methods dealing with text will work properly as expected and the callers can identify an absolute position of the first illegal JSON character after XMLStreamException has been thrown.
As usual, I'd like to thank the users who have reported the issues against Jettison and would like to encourage to get the patches provided.
I think over the time it has become clearer to me why Jettison is still being used, at least by some of CXF users, even though such powerful and popular processors as Jackson exist. Jettison is a very lightweight library, it has just few basic STAX XMLStreamReader and XMLStreamWriter implementations: this alone is not sufficient to produce a perfect JSON. But in CXF at least Jettison can be customized a lot to make it produce if not perfect but close enough JSON sequences.
This is what keeps it visible really in CXF land at least IMHO - the fact that the users can use it to write or read simple sequences (with many JSON consumers actually expecting simple enough sequences) but also nearly completely control the way a given sequence is produced or consumed. For example, people are talking about backward and forward compatibility with respect to processing XML - same can be achieved for JSON in CXF, all without code-related changes.
This is where its niche is, a bridge between JAXB and JSON, simple to medium complexity sequences, the possibility of the easy enough customization.
If you work with Jettison: please test the latest release and provide the feedback, thanks
Friday, December 28, 2012
Say Goodbye to HTTP URI Query Parameters
New Year is approaching fast but there is still some time to make one more New Year resolution.
Traditionally, when it comes to expressing the search requirements with HTTP URI, one uses URI query name and value, for example:
1. "/search/people?age=30&age=40"
2. "/search/people?ageFrom=30&ageTill=40"
First query can be read like this: "Find all people who are either 30 or 40 years old", the second - "Find all people older than 30 but younger than 40".
Plain query parameters are very widely used and actually very 'capable', one can invent a query parameter such as "ageFrom" to indicate the conditional requirement. It is not quite perfect in that the actual operator is "=" but the name implies it is not "equal to" but "greater or equal to", but it works, and probably reads better in some cases.
That said, the bigger the number of terms, the more tedious it can become to support creating the parameters like "ageFrom" and writing the actual code for figuring out which parameter means whether it is indeed the equality check as in "age=30" or say a "greater than" check as in "ageFrom=30". Supporting the finer-level checks such as "greater or equal to", as well as combining multiple type of checks can indeed become difficult to manage at the code level.
Consider always using FIQL expressions:
1. "/search/people?_s=age==30;age=40"
1.1 "/search/people?age==30;age=40"
1.2 "/search/people/age==30;age=40"
2. "/search/people?_s=age=ge=30;age=lt=40"
2.1 "/search/people?age=ge=30;age=lt=40"
2.2 "/search/people/age=ge=30;age=lt=40"
Does it look more complex ? I don't think it does but I can agree it may look a bit unusual at first, though the syntax is actually very easy to understand after typing it just for a bit of time.
Note a number of possible variations - in fact I guess I like options 1.2 and 2.2 most, the "optionality" aspect of URI query components does not make the whole URI represent a specific application state very cleanly (options 1, 1.1, 2, 2.1).
Also note the fine-level checks in 2.1/2.2 which are tricky to express with the plain queries, example, in this case it is "Find all people 30 years old or older but younger than 40 (exclusive)".
If you think about it, you have nothing to lose by starting using FIQL, for many cases it is nearly as simple and primitive as using plain query name and value pairs but the bonus comes immediately once you start expressing something more involved. As noted at the beginning of this post, plain queries are also capable in this regard - but the more complex the search requirements are - the less easy it becomes working with the plain queries.
Those Apache CXF users who have started experimenting with FIQL can utilize the existing FIQL converters, which is another plus point, consider the task of writing the code for converting plain query parameters to JPA2 expressions - it can be an involved task indeed - but with CXF JPA2 converter it is a walk in the park; as a side note - JPA2 converter now supports "count" extensions, for example, "find all the people living in London with more than 6 children".
Well, you may not be convinced that it is time to drop plain query name and value pairs. Never mind, just get CXF converting them internally to FIQL (which is very easy to do for CXF given that FIQL is a richer language, and still rely on the handy FIQL converters of your choice to interact with the data stores and completely generalize the search processing logic along the way. Offer different search endpoints for your users to enjoy working with, one accepting the traditional queries and another one accepting FIQL queries, with both endpoints using the same FIQL converters.
Still plenty of options to innovate in this well-explored space :-)!
Update: See also this earlier post from Abhishek Jain.
Happy New Year !
Traditionally, when it comes to expressing the search requirements with HTTP URI, one uses URI query name and value, for example:
1. "/search/people?age=30&age=40"
2. "/search/people?ageFrom=30&ageTill=40"
First query can be read like this: "Find all people who are either 30 or 40 years old", the second - "Find all people older than 30 but younger than 40".
Plain query parameters are very widely used and actually very 'capable', one can invent a query parameter such as "ageFrom" to indicate the conditional requirement. It is not quite perfect in that the actual operator is "=" but the name implies it is not "equal to" but "greater or equal to", but it works, and probably reads better in some cases.
That said, the bigger the number of terms, the more tedious it can become to support creating the parameters like "ageFrom" and writing the actual code for figuring out which parameter means whether it is indeed the equality check as in "age=30" or say a "greater than" check as in "ageFrom=30". Supporting the finer-level checks such as "greater or equal to", as well as combining multiple type of checks can indeed become difficult to manage at the code level.
Consider always using FIQL expressions:
1. "/search/people?_s=age==30;age=40"
1.1 "/search/people?age==30;age=40"
1.2 "/search/people/age==30;age=40"
2. "/search/people?_s=age=ge=30;age=lt=40"
2.1 "/search/people?age=ge=30;age=lt=40"
2.2 "/search/people/age=ge=30;age=lt=40"
Does it look more complex ? I don't think it does but I can agree it may look a bit unusual at first, though the syntax is actually very easy to understand after typing it just for a bit of time.
Note a number of possible variations - in fact I guess I like options 1.2 and 2.2 most, the "optionality" aspect of URI query components does not make the whole URI represent a specific application state very cleanly (options 1, 1.1, 2, 2.1).
Also note the fine-level checks in 2.1/2.2 which are tricky to express with the plain queries, example, in this case it is "Find all people 30 years old or older but younger than 40 (exclusive)".
If you think about it, you have nothing to lose by starting using FIQL, for many cases it is nearly as simple and primitive as using plain query name and value pairs but the bonus comes immediately once you start expressing something more involved. As noted at the beginning of this post, plain queries are also capable in this regard - but the more complex the search requirements are - the less easy it becomes working with the plain queries.
Those Apache CXF users who have started experimenting with FIQL can utilize the existing FIQL converters, which is another plus point, consider the task of writing the code for converting plain query parameters to JPA2 expressions - it can be an involved task indeed - but with CXF JPA2 converter it is a walk in the park; as a side note - JPA2 converter now supports "count" extensions, for example, "find all the people living in London with more than 6 children".
Well, you may not be convinced that it is time to drop plain query name and value pairs. Never mind, just get CXF converting them internally to FIQL (which is very easy to do for CXF given that FIQL is a richer language, and still rely on the handy FIQL converters of your choice to interact with the data stores and completely generalize the search processing logic along the way. Offer different search endpoints for your users to enjoy working with, one accepting the traditional queries and another one accepting FIQL queries, with both endpoints using the same FIQL converters.
Still plenty of options to innovate in this well-explored space :-)!
Update: See also this earlier post from Abhishek Jain.
Happy New Year !
Wednesday, December 12, 2012
FIQL and JPA2 Queries In Action
I've been focusing quite a lot recently on enhancing CXF Search extension module, by improving the existing converters and creating the new ones, making sure the parser is configurable, flexible and capable of mapping arbitrary property names to the properties of the bean capturing the search expression, and improving the documentation.
Andy Michalec created a FIQL parser quite a long time ago, it's been around for a while really, but it is only since Jeff Wang provided an initial FIQL to JPA2 converter patch that it kind of struck me how important it was to ensure the utility converters for mainstream and most popular technologies for querying the data stores were available.
With all the documentation and code improvements, it is still not quite good till it is actually demonstrated somehow, and this is exactly what I've spent the last few days upon, on enhancing the existing Talend ESB jaxrs-advanced demo to show how the client can type the queries with SearchConditionBuilder without having to type FIQL expressions manually and get the expressions seamlessly converted to JPA2 TypedQuery and CriteriaQuery, with Tuple mixed in, and the matching data returned to the client, all with the help of FIQL to JPA2 converter.
Let me comment on the actual demo enhancements in more detail.
First check the client code, the "useSearchService" function, starting from the line 194 and more specifically from line 205. IMHO expressing the query with the help of the fluent query builder (also created by Andy) is quite cool, it is definitely more descriptive with respect to what is actually expected, and it is the specific query language agnostic, it is FIQL by default but can be something else.
The builder can build whatever advanced query expression is needed, though practically speaking I would not expect massive expressions being created.
Now lets move to the server code. SearchService is one which actually handles the client requests and all it does it delegates to PersonInfoStorage which deals with querying the data. Note, SearchService works with CXF SearchContext by expecting it to extract the search expression from the current URI query component (default mode) or getting the expression from URI path and submitting it to SearchContext.
The main and in fact the single demo domain entity is Person but it is the one which is recursive, with children and parents, ancestors and descendants linked to. I haven't modified these relationships to get CXF JPA2 converter working properly, the only thing I did I added a couple of missing Person setters, added JPA2 annotations and also a hack required for JAXB RI capable of dealing with recursive structures (see the end of Person code).
The Person model is initialized in PersonInfoStorage init method (see the end of the file), where the injected JPA2 EntityManager is used - it could've been done elsewhere but was good enough for me for the purpose of the demo.
Next check getTypedQueryPerson (line 68) - see how straightforward it is to get the FIQL expression transparently converted to JPA2 TypedQuery, the comments in the code should make it very easy to understand.
Note, Person is a recursive and possibly a very deep structure and one may not necessarily want to fetch all the Person representation back to the client. A number of options exists for dealing with this issue including using the intrusive JAXB XmlTransient annotation but using JPA2 Tuple is one of the most elegant ones.
Using Tuple is one of JPA2 options for having the response shaped into simpler or different structures and getCriteriaQueryPerson method shows how it can be easily done by having the query returning the data sufficient for initializing a simple PersonInfo representation. One needs to get OpenJPA auto-generating the
metamodel classes for the tuple selections working and you can see how it can be done here, this tip helped me a lot.
Also note that PersonInfoStorage has the injected bean properties passed to SearchContext. Why this may have to be done is explained here but in short it lets to get the property names used in query language completely decoupled from the corresponding properties of the capturing bean, for example, in the demo case, the client can type "builder.is('childName').equalTo('Fred')" and have it working with the 'childName' correctly mapped to "children.name", where "children" points to a Person collection of children. This makes it simpler and easier to work with for the client, while keeping the internals of how the properties are actually linked to each other completely opaque. That is cool, I can hear you saying :-)
Finally have a look at how JPA2 EntityManager is initialized and injected. I started with arguably a simpler approach, I basically used Spring ORM module to get the entity manager wired in, see this beans.xml. This actually back-fired on me when I tried to make the demo working in Karaf - Spring ORM needs to see persistence.xml and is not capable on its own of inspecting OSGI Meta-Persistence property set up in the common module's pom.xml so I just ended up duplicating persistence.xml in both common and service modules.
On the TODO list is to follow an excellent tutorial from Christian and make the demo working with OSGi JPA Service. Perhaps someone from the community will be interested in doing a related pull request ?
So this is it and hope you'll find something interesting in this demo, enjoy !
Andy Michalec created a FIQL parser quite a long time ago, it's been around for a while really, but it is only since Jeff Wang provided an initial FIQL to JPA2 converter patch that it kind of struck me how important it was to ensure the utility converters for mainstream and most popular technologies for querying the data stores were available.
With all the documentation and code improvements, it is still not quite good till it is actually demonstrated somehow, and this is exactly what I've spent the last few days upon, on enhancing the existing Talend ESB jaxrs-advanced demo to show how the client can type the queries with SearchConditionBuilder without having to type FIQL expressions manually and get the expressions seamlessly converted to JPA2 TypedQuery and CriteriaQuery, with Tuple mixed in, and the matching data returned to the client, all with the help of FIQL to JPA2 converter.
Let me comment on the actual demo enhancements in more detail.
First check the client code, the "useSearchService" function, starting from the line 194 and more specifically from line 205. IMHO expressing the query with the help of the fluent query builder (also created by Andy) is quite cool, it is definitely more descriptive with respect to what is actually expected, and it is the specific query language agnostic, it is FIQL by default but can be something else.
The builder can build whatever advanced query expression is needed, though practically speaking I would not expect massive expressions being created.
Now lets move to the server code. SearchService is one which actually handles the client requests and all it does it delegates to PersonInfoStorage which deals with querying the data. Note, SearchService works with CXF SearchContext by expecting it to extract the search expression from the current URI query component (default mode) or getting the expression from URI path and submitting it to SearchContext.
The main and in fact the single demo domain entity is Person but it is the one which is recursive, with children and parents, ancestors and descendants linked to. I haven't modified these relationships to get CXF JPA2 converter working properly, the only thing I did I added a couple of missing Person setters, added JPA2 annotations and also a hack required for JAXB RI capable of dealing with recursive structures (see the end of Person code).
The Person model is initialized in PersonInfoStorage init method (see the end of the file), where the injected JPA2 EntityManager is used - it could've been done elsewhere but was good enough for me for the purpose of the demo.
Next check getTypedQueryPerson (line 68) - see how straightforward it is to get the FIQL expression transparently converted to JPA2 TypedQuery, the comments in the code should make it very easy to understand.
Note, Person is a recursive and possibly a very deep structure and one may not necessarily want to fetch all the Person representation back to the client. A number of options exists for dealing with this issue including using the intrusive JAXB XmlTransient annotation but using JPA2 Tuple is one of the most elegant ones.
Using Tuple is one of JPA2 options for having the response shaped into simpler or different structures and getCriteriaQueryPerson method shows how it can be easily done by having the query returning the data sufficient for initializing a simple PersonInfo representation. One needs to get OpenJPA auto-generating the
metamodel classes for the tuple selections working and you can see how it can be done here, this tip helped me a lot.
Also note that PersonInfoStorage has the injected bean properties passed to SearchContext. Why this may have to be done is explained here but in short it lets to get the property names used in query language completely decoupled from the corresponding properties of the capturing bean, for example, in the demo case, the client can type "builder.is('childName').equalTo('Fred')" and have it working with the 'childName' correctly mapped to "children.name", where "children" points to a Person collection of children. This makes it simpler and easier to work with for the client, while keeping the internals of how the properties are actually linked to each other completely opaque. That is cool, I can hear you saying :-)
Finally have a look at how JPA2 EntityManager is initialized and injected. I started with arguably a simpler approach, I basically used Spring ORM module to get the entity manager wired in, see this beans.xml. This actually back-fired on me when I tried to make the demo working in Karaf - Spring ORM needs to see persistence.xml and is not capable on its own of inspecting OSGI Meta-Persistence property set up in the common module's pom.xml so I just ended up duplicating persistence.xml in both common and service modules.
On the TODO list is to follow an excellent tutorial from Christian and make the demo working with OSGi JPA Service. Perhaps someone from the community will be interested in doing a related pull request ?
So this is it and hope you'll find something interesting in this demo, enjoy !
Subscribe to:
Posts (Atom)