tag:blogger.com,1999:blog-8752149020502332042024-03-25T09:30:39.367-07:00Code NewsIdeas and snippetsAnonymoushttp://www.blogger.com/profile/05704149010128055277noreply@blogger.comBlogger9125tag:blogger.com,1999:blog-875214902050233204.post-9461161585420357552014-09-27T03:10:00.000-07:002014-09-27T03:55:14.367-07:00Getting Scalatra to work on Google App Engine - Part 2In the <a href="http://www.gabiaxel.com/2014/09/getting-scalatra-to-work-on-google-app.html">previous post</a> we made the necessary modifications to Scalatra to make it compatible with Servlets API 2.5 , which allow us to use it on App Engine. One compromise we had to make is to use web.xml to register all the servlets, instead of doing it programmatically.<br />
<br />
There is indeed no way to make it possible to register the servlets programmatically in a 2.5 API environment we have no control of, but we can work around it by not really using servlets. This is actually a very old concept in Java web frameworks - register just one servlet in web.xml and have it dispatch the request to application non-servlet handlers. With a little work we can modify Scalatra to work this way, taking advantage of its API, and using an internal mapping mechanism for the top level resources, instead of the Servlet 3.0 registration.<br />
<br />
Do note that as opposed to the changes we made in the previous post, the changes demonstrated here result in a different way the requests flow in your application, which may or may not affect your specific cases, especially when you have different frameworks/components in your web tier.<br />
<br />
One of the objectives in the solution presented here is to stick to Scalatra's API as much as possible, so that it would be easier to port existing Scalatra code to App Engine, and to drop this solution when App Engine upgrades to Servlet API 3.0+ (if/whenever that happens). <br />
<br />
The steps we need to take are:<br />
<ul>
<li>Implement a resource class that will operate similar to ScalatraServlet
but will ignore the URI prefix that corresponds to the top-level mapping</li>
<li>Implement a mapping structure to back the mounting operation</li>
<li>Override Scalatra's enriched ServletContext mount operation to delegate to the above mapping</li>
<li>Implement a dispatcher servlet that will use the above mapping to dispatch requests to the appropriate resource</li>
</ul>
First we implement our "resource" class (think JAX-RS resource or SpringMVC controller). Since it should be almost identical to ScalatraServlet, we inherit from it, and the only change we need to make is to trim the URI prefix from the top-level mapping, because Scalatra's original behavior is to use the part of the URI after the servlet mapping, and we need to use the part after the dispatcher mapping. Therefore we add a member to hold the length of the top-level mapping, and override requestPath() to return the path after that.<br />
<br />
<pre class="brush: scala">package org.scalatra.gae
import org.scalatra.ScalatraServlet
import javax.servlet.http.HttpServletRequest
import org.scalatra.Handler
/**
* Instances of this class are meant to be mounted via
* [[org.scalatra.gae.AppMapper]] , as opposed to
* [[javax.servlet.ServletContext]], which cannot be done in API 2.5 .
*/
class ScalatraResource extends ScalatraServlet {
/**
* The length of the top-level URI mapping
*/
protected[gae] var basePathLength: Int = _
/*
* Trim the top-level mapping from the URI before using Scalatra's mapping
*/
override def requestPath(implicit request: HttpServletRequest): String = {
super.requestPath(request).substring(basePathLength)
}
}</pre>
<br />
To store the mappings, we implement an object that lets us add (mount) mapping of URI prefixes to resources, and get a resource that matches a URI prefix. We use a mutable map for storage. When we mount a resource, we set the top-level mapping length so it knows how to trim it.<br />
<br />
<pre class="brush: scala">package org.scalatra.gae
/**
* This object holds the top-level resource mappings
*/
object AppMapper {
val mapping = scala.collection.mutable.Map[String, ScalatraResource]()
/*
* Map a URI prefix to a resource
*/
def mount(handler: ScalatraResource, path: String) {
// Consistent handling of "/path", "/path/" and "/path/*"
val fixedPath = if (path.endsWith("/*"))
path.stripSuffix("*")
else if (!path.endsWith("/"))
path + "/"
else
path
handler.basePathLength = fixedPath.length - 1
mapping.put(fixedPath, handler)
}
/*
* Get the resource that matches the prefix of a URI
*/
def getHandler(uri: String) = mapping.find(m => uri.startsWith(m._1))
}</pre>
<br />
We could use AppMapper directly from our code, but to keep it close to the Scalatra way we will extend Scalatra's enriched ServletContext class and update ServletApiImplicits so our ScalatraBootstrap code will be decoupled from this solution.<br />
<br />
<pre class="brush: scala">package org.scalatra.gae
import org.scalatra.servlet.RichServletContext
import javax.servlet.ServletContext
/**
* Enriched [[javax.servlet.ServletContext]] which delegates the mounting
* operation to application-level mapping, instead of
* [[javax.servlet.ServletContext#addServlet(String, javax.servlet.Servlet)]]
* which is not available in API 2.5
*/
class RichAppServletContext(sc: ServletContext) extends RichServletContext(sc) {
def mount(handler: ScalatraResource, urlPattern: String) = AppMapper.mount(handler, urlPattern)
}</pre>
<br />
<br />
<pre class="brush: scala">package org.scalatra
package servlet
import javax.servlet.ServletContext
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
import javax.servlet.http.HttpSession
import org.scalatra.gae.RichResponseLocalStatus
import org.scalatra.gae.RichAppServletContext
trait ServletApiImplicits {
implicit def enrichRequest(request: HttpServletRequest): RichRequest =
RichRequest(request)
// Changed to overcome lack of HttpServletResponse.getStatus() in Servlet API 2.5
implicit def enrichResponse(response: HttpServletResponse): RichResponse =
new RichResponseLocalStatus(response)
implicit def enrichSession(session: HttpSession): RichSession =
RichSession(session)
// Changed to overcome the lack of ServletContext.mount() in Servlet API 2.5
implicit def enrichServletContext(servletContext: ServletContext): RichAppServletContext =
new RichAppServletContext(servletContext)
}
object ServletApiImplicits extends ServletApiImplicits
</pre>
<br />
Finally we implement the dispatcher servlet. It uses the request URI to get the matching resource instance from AppMapper and dispatches the request to it.<br />
<br />
<pre class="brush: scala">package org.scalatra.gae
import scala.collection.JavaConversions._
import javax.servlet.http.HttpServlet
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
/**
* This is the only servlet that needs to be registered in web.xml .
* It dispatches the request to the resource that matches the URI prefix
* as mounted to [[org.scalatra.gae.AppMapper]]
*/
class Dispatcher extends HttpServlet {
override def service(request: HttpServletRequest, response: HttpServletResponse) {
val uri = request.getRequestURI.substring(request.getServletPath().length())
val o = AppMapper.getHandler(uri)
if (o.isDefined) {
val (basePath, handler) = o.get
handler.handle(request, response)
}
}
}
</pre>
Now all we need to do in our application code is:<br />
<ul>
<li>Register and map the Dispatcher servlet in web.xml</li>
<li>Inherit from ScalatraResource instead of ScalatraServlet</li>
</ul>
Other than that, our code would be similar to any Scalatra application on a Servlet API 3.0+ environment, including calls to ServletContext.mount() in ScalatraBootstrap.<br />
<br />
<b><a href="https://github.com/GabiAxel/scalatra-appengine">A complete code example is available here.</a></b><br />
<br />
This is not the most generic code, for example - it doesn't handle filters, but it is a working starting point to get Scalatra to work on App Engine with minimum changes. If you have ideas for improvements - I'd love to know.Anonymoushttp://www.blogger.com/profile/05704149010128055277noreply@blogger.com2tag:blogger.com,1999:blog-875214902050233204.post-91922665859904306062014-09-10T09:52:00.001-07:002014-09-27T04:02:21.885-07:00Getting Scalatra to work on Google App Engine - Part 1<a href="http://scalatra.org/">Scalatra</a> is a neat lightweight Scala web framework. Scalatra 2.3.0 is based on the Servlet API 3.1 , while App Engine Java runtime only supports Servlet API 2.5 . App Engine imposes additional restrictions as described <a href="http://scalatra.org/2.3/guides/deployment/google-app-engine.html">here</a>, but they are not as significant as lack of support for Servlet 3.0/3.1 .<br />
<br />
After digging and experimenting, I succeeded in getting Scalatra to work on App Engine with a few workarounds. Basically we need to refrain from using Servlet 3.0/3.1 specific features in our code, and override Scalatra's parts that do use them with Servlet 2.5 compatible alternatives.<br />
<br />
The first obstacle you'll encounter is that you can't mount your servlets and filters programmatically in your ScalatraBootstrap class like this:<br />
<br />
<pre class="brush: scala">import org.scalatra.LifeCycle
import javax.servlet.ServletContext
class ScalatraBootstrap extends LifeCycle {
override def init(context: ServletContext) {
// This will fail
context mount (new MyCustomServlet, "/*")
}
}</pre>
<br />
Instead, you leave the init() method empty, and add your servlets and filters to web.xml :<br />
<br />
<pre class="brush: xml"><servlet>
<servlet-name>my-custom-servlet</servlet-name>
<servlet-class>MyCustomServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>my-custom-servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</pre>
<br />
Then, at runtime when accessing a path which is mapped by your Scalatra endpoints, you will encounter a NoSuchMethodError because Scalatra attempts to call HttpServletResponse.getStatus(), which was added in Servlet API 3.0 . The problematic code is in RichResponse.status(). RichResponse is an implicit replacement for HttpServletResponse as defined in ServletApiImplicits.enrichResponse(). To overcome the reading of the status from the original response, we'll subclass RichResponse and change the setter and getter of the status to use a local variable:<br />
<br />
<pre class="brush: scala">import org.scalatra.servlet.RichResponse
import javax.servlet.http.HttpServletResponse
import org.scalatra.ResponseStatus
class RichResponseLocalStatus(response:HttpServletResponse) extends RichResponse(response) {
var statusCode:Int = _
override def status = ResponseStatus(statusCode)
override def status_=(statusLine: ResponseStatus) {
statusCode = statusLine.code
super.status_=(statusLine)
}
}</pre>
<br />
The Scalatra code made it impossible to override the implicit definition for our need, so we have to rewrite ServletApiImplicits to look like this:<br />
<br />
<pre class="brush: scala">package org.scalatra
package servlet
import javax.servlet.ServletContext
import javax.servlet.http.{HttpServletRequest, HttpServletResponse, HttpSession}
import test.RichResponseCustom
trait ServletApiImplicits {
implicit def enrichRequest(request: HttpServletRequest): RichRequest =
RichRequest(request)
implicit def enrichResponse(response: HttpServletResponse): RichResponse =
// This is changed
new RichResponseLocalStatus(response)
implicit def enrichSession(session: HttpSession): RichSession =
RichSession(session)
implicit def enrichServletContext(servletContext: ServletContext): RichServletContext =
RichServletContext(servletContext)
}
object ServletApiImplicits extends ServletApiImplicits</pre>
<br />
Remember to place the changed ServletApiImplicits with your sources in the "org.scalatra.servlet" package. If you place it in another JAR, remember to make sure it takes precedence over Scalatra's JAR using <a href="https://developers.google.com/appengine/docs/java/#Java_Class_loader_JAR_ordering">App Engine's classloader JAR ordering</a>.<br />
<br />
That's it. It's not a perfect solution as it won't support Servlet 3.0/3.1 features such as asynchronous processing, and you have to define and map each servlet and filter in web.xml, but these are limitations you have to live with anyway on App Engine and this solution does let you use the nice and clean Scalatra code to write your web tier.<br />
<br />
In the <a href="http://www.gabiaxel.com/2014/09/getting-scalatra-to-work-on-google-app_27.html">next post</a> we will implement an alternative mapping mechanism, which will allow us to reduce the web.xml code and call mount operations in our ScalatraBootstrap code.Anonymoushttp://www.blogger.com/profile/05704149010128055277noreply@blogger.com0tag:blogger.com,1999:blog-875214902050233204.post-4574358292207420832014-05-25T10:28:00.000-07:002014-05-25T10:28:11.835-07:00Spring Social Google 1.0.0 Reaches General AvailabilityI am happy to announce the release of Spring Social Google 1.0.0.RELEASE ! I would like to thank everyone who contributed by testing and submitting issues and pull requests.<br />
<br />
Spring Social Google contains bindings to Google Plus, Google Tasks and Google Drive APIs, and allows you to use any Java client library for any Google API while using Spring Social for authentication and connection management.<br />
<br />
Project on GitHub: <a href="https://github.com/GabiAxel/spring-social-google">https://github.com/GabiAxel/spring-social-google</a><br />
<br />
Distribution bundle: <a href="https://github.com/GabiAxel/spring-social-google/releases/tag/1.0.0.RELEASE">https://github.com/GabiAxel/spring-social-google/releases/tag/1.0.0.RELEASE</a><br />
<br />
Reference manual: <a href="http://gabiaxel.github.io/spring-social-google-reference/">http://gabiaxel.github.io/spring-social-google-reference/</a><br />
<br />
JavaDoc: <a href="http://gabiaxel.github.io/spring-social-google-javadoc/">http://gabiaxel.github.io/spring-social-google-javadoc/</a><br />
<br />
Example application: <a href="https://github.com/GabiAxel/spring-social-google-example">https://github.com/GabiAxel/spring-social-google-example</a><br />
<br />
To use with Maven add the following code to your POM:<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace;"><dependency></span><br />
<span style="font-family: "Courier New",Courier,monospace;"> <groupId>org.springframework.social</groupId></span><br />
<span style="font-family: "Courier New",Courier,monospace;"> <artifactId>spring-social-google</artifactId></span><br />
<span style="font-family: "Courier New",Courier,monospace;"> <version>1.0.0.RELEASE</version><br /></dependency></span></blockquote>
<br />
<h3>
Creating a Google Cloud Project and Using it with Spring Social Google</h3>
<br />
Navigate to <a href="https://console.developers.google.com/project">https://console.developers.google.com/project</a><br />
<br />
Click "Create Project" and enter a name and ID for the project.<br />
<br />
Enter the project and in the left menu select "APIs & Auth". In "APIs" activate the APIs you want to use in the application. The example application uses <b>Google+ API</b> and <b>Tasks API</b>.<br />
<br />
In the left menu go to "Credentials" and click "Create new client ID". For "Application Type" choose "<b>Web Application</b>" and for "Authorized Redirect URI" enter "<b>http://localhost:8080/signin/google</b>".<br />
<br />
The new set of credentials will be added. Note the "Cliend ID" and "Client Secret" values - we will use them when running the example application.<br />
<br />
Get the example application from GitHub:<br />
<span style="font-family: "Courier New",Courier,monospace;">git clone git://github.com/GabiAxel/spring-social-google-example.git</span><br />
<br />
Enter the application directory and run it with Tomcat (replace CLIENT_ID and CLIENT_SECRET with the values you saw in Google Developers Console):<br />
<span style="font-family: "Courier New",Courier,monospace;">cd spring-social-google-example</span><br />
<span style="font-family: "Courier New",Courier,monospace;">mvn tomcat7:run \</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> -Dgoogle.clientId=<b>CLIENT_ID</b> \</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> -Dgoogle.clientSecret=<b>CLIENT_SECRET</b></span><br />
<br />
The application will run at http://localhost:8080/<br />
<br />
<h3>
The Road Ahead</h3>
<br />
There is no shortage of Google APIs. My current though is to proceed to YouTube and Calendar, but I really want to know what you want, so please submit your requests and issues in the GitHub project.<br />
<br />
Enjoy using Spring Social Google! Anonymoushttp://www.blogger.com/profile/05704149010128055277noreply@blogger.com27tag:blogger.com,1999:blog-875214902050233204.post-75411021997315074942012-04-09T11:55:00.000-07:002012-04-09T11:55:36.446-07:00Spring Social Google First Milestone Is Out<br />
<br />
I'm happy to announce that the first milestone of <a href="https://github.com/GabiAxel/spring-social-google">Spring Social Google</a> is out! Since the project started I received a lot of feedback from the community that helped shape this milestone and I would like to thank everyone who helped with suggestions, bug reports, patches and kind words.<br />
<br />
This milestone includes integration with <a href="https://developers.google.com/+/api/">Google+</a>, <a href="https://developers.google.com/google-apps/contacts/poco/index">Portable Contacts</a> and <a href="https://developers.google.com/google-apps/tasks/">Google Tasks</a>. It also lets you integrate with the <a href="http://code.google.com/p/gdata-java-client/">GData Java Client Library</a>, letting you use Spring Social Google for authentication and authorization, and applying the OAuth2 access token to an instance of a GData client. Please see the <a href="https://github.com/GabiAxel/spring-social-google/wiki/Spring-Social-Google-Reference-Manual">reference manual</a> for usage instructions.<br />
<br />
The <a href="https://github.com/GabiAxel/spring-social-google/tree/master/spring-social-google-quickstart/spring-social-quickstart">example application</a> demonstrates most of the available functionality. You can see it in action <a href="http://googleapis.cloudfoundry.com/">here</a>.<br />
<br />
To use Spring Social Google in a maven project, add the following repository and dependency to your pom.xml :<br />
<br />
<pre class="brush: xml"><repository>
<id>spring.social.google</id>
<name>Spring Social Google</name>
<url>https://github.com/GabiAxel/maven/raw/master/</url>
</repository>
...
<dependency>
<groupId>org.springframework.social</groupId>
<artifactId>spring-social-google</artifactId>
<version>1.0.0.M1</version>
</dependency></pre>
<br />
<br />
or download the JAR <a href="https://github.com/GabiAxel/spring-social-google/downloads">here</a>. <br />
<br />
The project roadmap mostly depends on community feedback. Integration with more Google APIs will be added and you can help decide which will be first, so let me know what you think.<br />
<br />
Enjoy using Spring Social Google!Anonymoushttp://www.blogger.com/profile/05704149010128055277noreply@blogger.com30tag:blogger.com,1999:blog-875214902050233204.post-22999886014933369292011-10-27T06:08:00.000-07:002011-11-02T00:09:19.059-07:00Replacing javac with eclipse compiler in MavenI was working on a Java project with eclipse where I used cyclic dependencies. Specifically I implemented the <a href="http://arcbees.wordpress.com/2010/09/03/reversing-the-mvp-pattern-and-using-uihandler/">Reverse MVP pattern</a> with <a href="http://code.google.com/p/gwt-platform/">GWT Platform</a>. Everything went well in as long as I was using eclipse to compile the project, but once I tried to use Maven to compile the project, I got compilation errors for every case where I had a cyclic dependency. I figured that if eclipse is good enough to compile the sources in development time, it might as well be used in build time instead of JDK's javac. Here is the maven-compiler-plugin configuration from the project POM I initially had:
<pre class="brush: xml"><plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin></pre>
In order to replace javac with eclipse compiler we need to do two things: we need to add a dependency for plexus-compiler-eclipse, and we need to tell the maven-compiler-plugin to use the eclipse compiler <a href="http://maven.apache.org/plugins/maven-compiler-plugin/non-javac-compilers.html">as described here</a>. Here is the updated configuration:
<pre class="brush: xml"><plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<compilerId>eclipse</compilerId>
<source>1.6</source>
<target>1.6</target>
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-compiler-eclipse</artifactId>
<version>1.8.2</version>
</dependency>
</dependencies>
</plugin></pre>
After that it was possible to build the project with Maven.Anonymoushttp://www.blogger.com/profile/05704149010128055277noreply@blogger.com12tag:blogger.com,1999:blog-875214902050233204.post-41284743642981000302011-09-22T03:31:00.000-07:002012-04-09T11:27:51.007-07:00Spring Social Meets Google APIsFor the past several weeks I have been working on the <a href="https://github.com/GabiAxel/spring-social-google">Spring Social Google</a> project. The goal of <a href="http://www.springsource.org/spring-social">Spring Social</a> is to act as an abstraction layer between your application code and various social APIs, and removes the need for you to deal with authentication and HTTP-Java mapping, and now you can use it with a growing number of Google APIs, starting with the <a href="http://code.google.com/apis/contacts/">Contacts API</a> and <a href="https://developers.google.com/+/api/">Google+ API</a>.<br />
<br />
<b>Why do I need this? Google already provides Java libraries for its APIs.</b><br />
<br />
Indeed you can use the Java libraries from Google, but there are cases where you may benefit from using Spring Social instead. For once, Spring Social comes with an authentication mechanism that removes the need for you to write Servlet code for the stages of the OAuth2 process. You can read about it <a href="http://static.springsource.org/spring-social/docs/1.0.x/reference/html/signin.html">here</a>. Another goodie Spring Social provides is connection management and persistence, so you don't have to deal with session management and and writing your own database schema to store the users' access tokens. You can read about it <a href="http://static.springsource.org/spring-social/docs/1.0.x/reference/html/serviceprovider.html">here</a>. You can see how to set up both mechanisms in the <a href="https://github.com/GabiAxel/spring-social-google/tree/master/spring-social-google-quickstart/spring-social-quickstart">example application</a>, specifically in <a href="https://github.com/GabiAxel/spring-social-google/blob/master/spring-social-google-quickstart/spring-social-quickstart/src/main/java/org/springframework/social/quickstart/config/SocialConfig.java">SocialConfig.java</a> , <a href="https://github.com/GabiAxel/spring-social-google/blob/master/spring-social-google-quickstart/spring-social-quickstart/src/main/java/org/springframework/social/quickstart/config/WebMvcConfig.java">WebMvcConfig.java</a> and <a href="https://github.com/GabiAxel/spring-social-google/blob/master/spring-social-google-quickstart/spring-social-quickstart/src/main/webapp/WEB-INF/spring-config.xml">spring-config.xml</a> .<br />
<br />
Spring Social also takes a different approach than Google's Java libraries in that Google's libraries provide a Java API that mirrors the underlying REST API (be it Atom, Portable Contacts or other), while Spring Social aims to provide you with data structure and operations you are likely to use.<br />
Let's use both tools to write a program that fetches the user's contacts and prints their names and primary e-mail addresses.<br />
<br />
Here is how it's done with Google Contact API Java library:<br />
<br />
<pre class="brush: java">ContactsService service = getContactsService();
URL feedUrl = new URL("https://www.google.com/m8/feeds/contacts/default/full");
ContactFeed resultFeed = service.getFeed(feedUrl, ContactFeed.class);
for (ContactEntry entry : resultFeed.getEntries()) {
String fullName = entry.getName().getFullName().getValue();
String email = null;
for(Email e : entry.getEmailAddresses() {
if(email.getPrimary) {
email = e;
break;
}
}
System.out.println(fullName + " " + email);
}</pre>
<br />
And here is the equivalent Spring Social Google code:<br />
<br />
<pre class="brush: java">GoogleOperations google = getGoogleOperations();
List<Contact> contacts = google.contactOperations().getContactList();
for(Contact contact : contacts) {
String fullName = contact.getFullName();
String email = contact.getPrimaryEmail();
System.out.println(fullName + " " + email);
}</pre>
<br />
It's up to you to decide if you prefer the simplicity of Spring Social or the flexibility of the Google API Java libraries.<br />
<br />
<b>Is the project stable? What is its roadmap?</b><br />
<br />
Spring Social Google is still at an early stage, so there are no builds and the API may change. Aside of the currently implemented Contacts and Google+ APIs, the project is expected to include more and more of Google APIs over time. You are welcome to <a href="https://github.com/GabiAxel/spring-social-google">download the sources</a> and play with the example application, which is also <a href="http://googleapis.cloudfoundry.com/">deployed on Cloud Foundry</a><br />
<br />
Enjoy and send feedback!Anonymoushttp://www.blogger.com/profile/05704149010128055277noreply@blogger.com2tag:blogger.com,1999:blog-875214902050233204.post-18982916165693686142011-07-30T23:00:00.000-07:002011-07-30T23:00:44.794-07:00Dynamically Adding Styles to HTML PagesI came into a situation where I needed to apply styles to the entire page after the page was loaded. Using techniques like targeting elements by their CSS selectors and applying styles to them with jQuery or similar tools would not be sufficient, because I would have to do it every time elements are added to the DOM and it would have required specifically adding a class (or some other attribute) to each element I wanted to apply the style to.<br />
<br />
The solution I ended up implementing was to add styles to the page dynamically using JavaScript. Normal browsers let you manipulate the Head element as any other element, so all I needed to do was to append the Style element as a child of the Head element, and set the style's inner HTML with the CSS content:<br />
<br />
<pre class="brush: js">function addCustomStyle() {
var style = document.createElement("style");
style.innerHTML = ".someclass {color: green;}";
var head = document.getElementsByTagName("head")[0];
head.appendChild(style);
}</pre><br />
Unsurprisingly like so many other cases, Internet Explorer has its own way of doing stuff. It doesn't allow manipulating the Head element as other elements, but it does provide an API for adding CSS rules to the document. Here is how it's done:<br />
<br />
<pre class="brush: js">function addCustomStyle() {
var style = document.createStyleSheet();
style.addRule(".someclass", "color: green;");
}</pre><br />
You could wrap the two methods with IE conditional tags ([if !IE] and [if IE]) so only one of them will actually be used depending on the browser, or you can come up with your own mechanism. If you are using GWT, deferred binding is perfect for this.Anonymoushttp://www.blogger.com/profile/05704149010128055277noreply@blogger.com2tag:blogger.com,1999:blog-875214902050233204.post-39285838415458246872011-01-20T01:20:00.000-08:002011-01-20T01:20:25.380-08:00Better Enum Mapping with HibernateJPA and Hibernate provides two ways to map enum fields to database fields: either map the enum value ordinal with @Enumerated(EnumType.ORDINAL) or the enum value name with @Enumerated(EnumType.STRING) . Both cases are not ideal, because it's very easy to make changes to the enum, such as changing values order or renaming values, and forgetting to migrate the existing values in the database accordingly. Actually the need to migrate existing data is not justified if you just want to change Java code.<br />
<br />
Here is a mechanism that lets you decouple the enum value names and ordinals from the data, while still making it easy to map enum fields to database columns.<br />
<br />
The solution can be specific to an enum type, but it would be better to have all your persistent enum types implement the same interface to reuse the mechanism. Let's define the PersistentEnum interface:<br />
<br />
<pre class="brush: java">public interface PersistentEnum {
int getId();
}
</pre><br />
and it will be implemented by enum types, for example:<br />
<br />
<pre class="brush: java">public enum Gender implements PersistentEnum {
MALE(0),
FEMALE(1);
private final int id;
Gender(int id) {
this.id = id
}
@Override
public int getId() {
return id;
}
}
</pre><br />
Now we need to define the Hibernate User Type that will do the conversion both ways. Each enum requires its own user type, so first we will code an abstract superclass that works with the PersistentEnum interface and then subclass it for each enum:<br />
<br />
<pre class="brush: java">public abstract class PersistentEnumUserType<T extends PersistentEnum> implements UserType {
@Override
public Object assemble(Serializable cached, Object owner)
throws HibernateException {
return cached;
}
@Override
public Object deepCopy(Object value) throws HibernateException {
return value;
}
@Override
public Serializable disassemble(Object value) throws HibernateException {
return (Serializable)value;
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
return x == y;
}
@Override
public int hashCode(Object x) throws HibernateException {
return x == null ? 0 : x.hashCode();
}
@Override
public boolean isMutable() {
return false;
}
@Override
public Object nullSafeGet(ResultSet rs, String[] names, Object owner)
throws HibernateException, SQLException {
int id = rs.getInt(names[0]);
if(rs.wasNull()) {
return null;
}
for(PersistentEnum value : returnedClass().getEnumConstants()) {
if(id == value.getId()) {
return value;
}
}
throw new IllegalStateException("Unknown " + returnedClass().getSimpleName() + " id");
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index)
throws HibernateException, SQLException {
if (value == null) {
st.setNull(index, Types.INTEGER);
} else {
st.setInt(index, ((PersistentEnum)value).getId());
}
}
@Override
public Object replace(Object original, Object target, Object owner)
throws HibernateException {
return original;
}
@Override
public abstract Class<T> returnedClass();
@Override
public int[] sqlTypes() {
return new int[]{Types.INTEGER};
}
}
</pre><br />
The interesting methods are nullSafeGet() which is called when the resultset from the database is mapped to an object, and nullSafeSet() which is called when the fields of an object are mapped to SQL parameters of insert/update/delete statements.<br />
<br />
The extension point is the abstract method returnedClass() - in every subclass we will override it so it returns the specific enum class. A User Type for the Gender enum defined above would like this:<br />
<br />
<pre class="brush: java">public class GenderUserType extends PersistentEnumUserType<Gender> {
@Override
public Class<Gender> returnedClass() {
return Gender.class;
}
}
</pre><br />
The last thing to do is to configure fields of enum types to use the appropriate user types:<br />
<br />
<pre class="brush: java">@Entity
public class Person {
@Type(type="it.recompile.GenderUserType")
private Gender gender;
// other fields and methods...
}
</pre><br />
Note that the type attribute should contain the fully qualified class of the user type, including the package.<br />
<br />
That's it - now you can safely make changes to your enum classes without worrying about problems with existing data, as long as you don't change the id values in the constructors (which you have no reason to do).Anonymoushttp://www.blogger.com/profile/05704149010128055277noreply@blogger.com13tag:blogger.com,1999:blog-875214902050233204.post-22875556719238694732011-01-19T05:53:00.000-08:002011-01-19T05:53:45.433-08:00Simplifying JPA Code with HadesJPA is not that much fun anymore. It was a great improvement compared to plain JDBC and XML mapping of many persistence frameworks, but after a while you come to realize that in many cases you need to write quite a lot of code to do very little work (like many other things in Java).<br />
<br />
Enters <a href="http://redmine.synyx.org/projects/show/hades">Hades</a>. In one sentence, it reduces the amount of JPA code by using convention over configuration. The Hades documentation is clear and comprehensive, so I won't explain it in detail here. I will demonstrate the process of migrating a simple JPA project to use Hades, something you will probably want to do once you get to know Hades.<br />
<br />
<span style="font-size: large;">Setting Up a JPA Project</span><br />
<br />
In this example we use Hibernate as the persistence provider and JUnit for the unit tests. If you want to use Maven, you just need to add the following dependencies to your POM:<br />
<br />
<pre class="brush: xml"><dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>3.6.0.Final</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<scope>test</scope>
</dependency> </pre><br />
Let's create a very simple persistent model class named User:<br />
<br />
<pre class="brush: java">@Entity
public class User {
@Id
@GeneratedValue(strategy=IDENTITY)
private Long id;
private String username;
private String fullName;
private User() {}
public User(String username, String fullName) {
this.username = username;
this.fullName = fullName;
}
public Long getId() {
return id;
}
public String getUsername() {
return username;
}
public String getFullName() {
return fullName;
}
} </pre><br />
A simple DAO interface:<br />
<br />
<pre class="brush: java">public interface UserDao {
void saveUser(User user);
User findById(Long id);
List<User> findByFullName(String fullName);
void deleteUser(User user);
}
</pre><br />
And of course there is a DAO implementation class, but we will not show it here, soon you will see why.<br />
<br />
No project is complete without unit tests, so here is a very simple one:<br />
<br />
<pre class="brush: java">public class UserDaoTest {
@Test
public void generalTest() {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("pu");
EntityManager em = emf.createEntityManager();
UserDao userDao = new UserDaoImpl(em);
final String username = "jsmith";
final String fullName = "John Smith";
final Long id;
// Save user
User user = new User(username, fullName);
userDao.saveUser(user);
id = user.getId();
// Find by ID
user = userDao.findById(id);
assertEquals(username, user.getUsername());
// Find by Full Name
List<User> results = userDao.findByFullName("John Smith");
assertEquals(1, results.size());
assertEquals(username, results.get(0).getUsername());
// Delete
userDao.deleteUser(user);
user = userDao.findById(id);
assertNull(user);
}
}
</pre><br />
Regarding implementation details: the findByFullName() method can be implemented either with a named query or with a criteria, it doesn't matter for our example.<br />
<br />
<span style="font-size: large;">Adding Hades</span><br />
<br />
Add Hades to your project. With Maven we add this dependency:<br />
<br />
<pre class="brush: xml"><dependency>
<groupId>org.synyx.hades</groupId>
<artifactId>org.synyx.hades</artifactId>
<version>2.0.1.RELEASE</version>
</dependency> </pre><br />
To make our DAO work with Hades, we make UserDao inherit from GenericDao<User, Long>. This is a Hades interface where the first type is the persistent class it will work with and the second type is the type of the persistent class identifier.<br />
Now we simply delete stuff. That's right - we delete the DAO implementation class, the named query (if you have one) and some of the DAO interface methods.<br />
<br />
The UserDao interface should now look like this:<br />
<br />
<pre class="brush: java">public interface UserDao extends GenericDao<User, Long> {
List<User> findByFullName(String fullName);
}
</pre><br />
But what about all the methods that we removed? They are no longer needed because GenericDao has equivalent methods, and Hades provides the implementation. Take a look at the JavaDoc of GenericDao to see what you get "for free".<br />
<br />
That's great, but doesn't findByFullName() need an implementation? That depends. For simple finder methods you can use method names that matches Hades conventions. In this case, the prefix "findBy" that precedes "FullName" means that this is a search query that uses the "fullName" property in the "where" clause, meaning Hades generates a this query from the method name: "from User where fullName = ?" .<br />
<br />
If we do want to write more complex queries, we can do it by annotating the method in the DAO interface. Let's change findByFullName() to use the "like" operator instead of "=" :<br />
<br />
<pre class="brush: java">public interface UserDao extends GenericDao<User, Long> {
@Query("from User where fullName like ?1")
List<User> findByFullName(String fullName);
}</pre>This makes much more sense (at least to me) than writing the query as part of the model code.<br />
<br />
So, if there is no implementation class (more correctly - Hades generates the implementation class at runtime), how do we instantiate the DAO ? We use Hades GenericDaoFactory. Let's change the unit test code accordingly: <br />
<pre class="brush: java">public class UserDaoTest {
@Test
public void generalTest() {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("pu");
EntityManager em = emf.createEntityManager();
GenericDaoFactory gdf = GenericDaoFactory.create(em);
UserDao userDao = gdf.getDao(UserDao.class);
// rest of the code as before
}
}
</pre>That's it. By using Hades we made our code much more clean because: <br />
<ul><li>We get the basic CRUD operations in every DAO out of the box</li>
<li>We don't need to write DAO implementation class in many cases</li>
<li>We write JPQL queries in the DAO interface and not in the model</li>
<li>We don't even need to write JPQL queries for simple cases where we can use conventional method names</li>
</ul>Although Hades removes the need to write DAO implementation code, sometimes we have no choice. Maybe we want to build a dynamic query or we simple want to migrate gradually to Hades while keeping existing JPA code. For this case we can write an additional custom DAO interface with an implementation, and make the Hades DAO inherit the custom DAO:<br />
<br />
<pre class="brush: java">public interface UserDaoCustom {
List<User> searchUsers(String username, String fullName);
}
</pre><br />
<pre class="brush: java">public class UserDaoImpl implements UserDaoCustom {
List<User> searchUsers(String username, String fullName) {
// implementation code...
}
}
</pre><br />
<pre class="brush: java">public interface UserDao extends GenericDao<User, Long>, UserDaoCustom {
@Query("from User where fullName like ?1")
List<User> findByFullName(String fullName);
} </pre><br />
When we use a custom DAO with implementation, we need to tell the Hades factory to use this implementation, so we modify one line the unit test code:<br />
<br />
<pre class="brush: java">UserDao userDao = gdf.getDao(UserDao.class, UserDaoImpl.class);</pre><br />
So there - you don't have to make any drastic changes to your codebase at once in order to benefit from Hades.<br />
<br />
There are plenty of nice features in Hades we didn't cover such as pagination, sorting, named parameters and Spring integration. I encourage you to read the <a href="http://redmine.synyx.org/projects/hades/wiki">Hades Documentation</a> to learn about its features. We will cover some of them in future posts.Anonymoushttp://www.blogger.com/profile/05704149010128055277noreply@blogger.com0