DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

The Latest Data Topics

article thumbnail
Fluent Navigation in JSF 2
In this article, the third in a series covering JavaServer Faces (JSF) 2.0 features contributed by Red Hat, or which Red Hat participated in extensively, you'll discover that getting around in a JSF 2 application is much simpler and requires less typing. With improved support for GET requests and bookmarkability, which the previous article covered, JSF 2 is decidely more nimble. But not at the cost of good design. JSF no longer has to encroach on your business objects by requiring action methods to return navigation outcomes, but can instead reflect on the state of the system when selecting a navigation case. This article should give you an appreciation for how intelligent the navigation system has become in JSF 2. Read the other parts in this article series: Part 1 - JSF 2: Seam's Other Avenue to Standardization Part 2 - JSF 2 GETs Bookmarkable URLs Part 3 - Part 4 - Part 5 - Three new navigation variants are going to be thrown at you in this article: implicit, conditional and preemptive. These new options are a sign that the JSF navigation system is becoming more adaptable to the real world. There's also a touch of developer convenience thrown in. Implicit navigation is particularly useful for developing application prototypes, where navigation rules just get in the way. This style of navigation interprets navigation outcomes as view IDs. As you move beyond prototyping, conditional navigation removes the coupling between the web and transactional tier because the navigation handler pulls information from your business components to select a navigation case. Preemptive navigation, which you were introduced to in the last article, can use either implicit navigation or declarative navigation rules to produce bookmarkable URLs at render time. Leveraging the navigation system to generate bookmarkable URLs allows JSF to add GET support while maintaining consistent, centralized navigation rules. Even with these new options, there's no telling what requirements your application might have for navigation. Thus, in JSF 2, you can finally query and modify the navigation cases; a new API has been introduced in JSF 2 that exposes the navigation rule set. Before we get into customizations, let's find out how these new variants make the navigation system more flexible and help prepare the user's next move. Hopefully you won't need those customizations after all. Flexible navigation choices The declarative navigation model in JSF was a move away from the explicit navigation "forward" selection by the action in Struts. Navigation transitions in JSF, which get matched based on current view ID, logical outcome and/or action expression signature, are described in the JSF descriptor (faces-config.xml) using XML-based rules. The matched transition indicates the next view to render and whether a client-side redirect should proceed rendering. Here's a typical example: /guess.xhtml #{numberGuessGame.guess} correct /gameover.xhtml While the JSF navigation model is clearer and arguably more flexible than in Struts, two fundamental problems remain. First, the action method is still required to return a navigation directive. The directive just happens to be a more "neutral" string outcome rather than an explicit type (i.e., ActionForward), but the coupling is just as tight and you loose type safety in the process, so is it really an improvement? The other issue is that you must define a navigation case to match that outcome, even in the simplest cases, which can be really tedious. So you can't make the argument that the navigation model is less obtrusive or more convenient. It's just stuck somewhere in between. To sum it up, the JSF navigation model is not flexible enough. It needs to accommodate different development styles better and it needs to be more self sufficient. On the one hand, your style or development phase may dictate waiving the declarative navigation rule abstraction. On the other hand, you may want to completely decouple your business objects from the navigation model, eradicating those arbitrary return value directives. JSF 2 gives you this broad range of options, and even let's you settle for a happy medium. The first option is provided by implicit navigation and the second conditional navigation. With implicit navigation, you can even use the current model without having to define the navigation rule right away. Let's unbox these two new alternatives, starting with implicit navigation. Implicit navigation JSF will post a form back to the current view (using the POST HTTP method) whenever the user performs an action, such a clicking a command button (hence the term "postback"). In the past, the only way to get JSF to advance to another view after the action is invoked (i.e., following the Invoke Application phase) was to define a navigation case in faces-config.xml. Navigation cases are matched based on the EL signature of the action method invoked and the method's return value converted to a string (the logical outcome). To cite an example, assume the user clicks on a button defined as follows: The preview() method on the bean named commandHandler returns a value to indicate the outcome of processing: public String preview() { // tidy, translate and/or validate comment return "success"; } These two criteria are joined in a navigation case that dictates which view is to be rendered next. /entry.xhtml #{commentHandler.preview} success /previewComment.xhtml If no navigation case can be matched, all JSF knows to do is render the current view again. So without a navigation case, there is no navigation. A quick shorthand, which is present in Seam, is to have the action method simply return the target view ID directly. In this case, you're effectively treating the logical outcome value as a view ID. This technique has been adopted in JSF 2 as implicit navigation. It's improved since Seam because you can choose to drop the view extension (e.g., .xhtml) and JSF will automatically add it back on for you when looking for a view ID. Therefore, it's no more invasive than the string outcome values you are currently returning. Implicit navigation comes into play when a navigation case cannot be matched using the existing mechanism. Here's how the logic outcome is processed in the implicit navigation case: Detect the presence of the ? character in the logical outcome If present, capture the query string parameters that follow it the ? character The special query string parameter faces-redirect=true indicates that this navigation should be issued using a client-side redirect If the logical outcome does not end with a file extension, append file extension of current view ID (e.g., .xhtml) If the logical outcome does not begin with a /, prepend the location of current view id (e.g., /, /admin/, etc.) Attempt to locate the template for the view ID If the template is found, create a virtual navigation case that targets the resolved view ID If the template is not found, skip implicit navigation Carry out the navigation case If the navigation case is not a redirect, build and render the target view in the same request If the navigation case is a redirect, build a redirect URL, appending the query string parameters captured earlier, then redirect to it Implicit navigation can be leveraged anywhere a logical outcome is interpreted. That includes: The return value of an action method The action attribute of a UICommand component (e.g., ) The outcome attribute of a UIOutcomeTarget (e.g., ) The handleNavigation() method of the NavigationHandler API Here's an example of the navigation to the preview comment view translated into implicit navigation. The return value is automatically decorated with a leading / and a trailing .xhtml. public String preview() { // tidy, translate and/or validate comment return "previewComment"; } The /previewComment.xhtml view will be rendered in the same request. If you want to redirect first, add the following flag in the query string of the return value: public String preview() { // tidy, translate and/or validate comment return "previewComment?faces-redirect=true"; } You can accomplish any navigation scenario using implicit navigation that you can today with a formal navigation case defined in faces-config.xml. Implicit navigation is designed as the fall-through case (after the explicit navigation rules are consulted). If it fails (i.e., the template cannot be located), and the JSF 2 ProjectStage is set to development, a FacesMessage is automatically generated to warn the developer of a possible programming error. Implicit navigation is great for prototyping and other rapid development scenarios. The major downside of implicit navigation is that you are further tying your business objects into the navigation model. Next we'll look conditional navigation, which provides an alternative that keeps your tiers loosely coupled. Conditional navigation Implicit navigation spotlights how invasive it is to put the onus on your business object to return a logic outcome just to make JSF navigation happy (and work). This coupling is especially problematic when you want to respond to user interface events using components in your business tier, a simplified architecture that is supported by both Seam and Java EE 6 to reduce the amount of glue code without increasing coupling. What would be more "logical" is to invert the control and have the navigation handler consult the state of the bean to determine which navigation case is appropriate. The navigation becomes contextual rather than static. That's what conditional navigation gives you. Conditional navigation introduces a condition as a new match criteria on the navigation case. It's defined in the element as a child of and expressed using an EL value expression. The value expression is evaluated each time the navigation case is considered. For any navigation case that matches, if a condition is defined, the condition must resolve to true for the navigation case to be considered a match. Here's an example of a conditional navigation case: #{registration.register} #{currentUser.registered} /account.xhtml As you can see, the condition doesn't necessarily have to reference a property on the bean that was invoked. It can be any state reachable by EL. Conditional navigation solves a secondary problem with the JSF navigation model, one of those little annoyances in JSF that was tedious to workaround. In JSF 1.2 and earlier, if your action method is a void method or returns a null value, interpreted in both cases as a null outcome, the navigation is skipped entirely. As a result, the current view is rendered again. The only workaround is to override the navigation handler implementation and change the behavior. That really throws a wrench in being able to cut the glue code between your UI and transactional tier. That changes with the introduction of conditional navigation. Since the condition provides either an alternative, or supplemental, match criteria to the logical outcome, navigation cases that have a condition are consulted even when the logical outcome is null or void. When the outcome is null, you can emulate switch statement to match a navigation case, switching on the condition criteria: #{identity.login} #{currentUser.admin} /admin/home.xhtml #{identity.login} #{currentUser.vendor} /vendor/home.xhtml #{identity.login} #{currentUser.client} /client/home.xhtml If you intend to simply match the null outcome in any case, you can use a condition that is verily true (which, admittedly, could be improved in JSF 2.1): #{identity.logout} #{true} /home.xhtml You can also use this fixed condition to provide a fall-through case. But wait, there's more! Having to itemize all the possible routes using individual navigation cases causes death by XML (a quite painful death). What if you wanted to delegate the decision to a navigation helper bean or involve a scripting language? There's good news. You can! The target view ID can be resolved from an EL value expression. Let's return to the login example and use a helper bean to route the user using one navigation case: #{identity.login} #{navigationHelper.userHomeViewId} Oh my goodness, how much nicer is that? The navigation helper can encapsulate the logic of inspecting the currentUser bean and determining the correct target view ID. In this section, we looked at two additional ways a navigation case is matched, increasing the overall flexibility of the navigation model. Implicit navigation maps logical outcomes directly to view IDs and conditional navigation reflects on contextual data to select a navigation case without imposing unnecessary coupling with the transactional tier. We're still looking at the same fundamental navigation model, though. In the next section, you'll see the navigation model used in a new role, and in a new place in the JSF life cycle, to generate bookmarkable links. Anticipating the user's next move Up to this point, the navigation handler only comes into play on a postback. Since user interface events trigger a "postback" to the current view, as mentioned earlier, the navigation handler kicks in after the Invoke Application phase to route the user to the next view. JSF 2 introduces a completely new use of the navigation handler by evaluating the navigation rules during the Render Response phase. This render-time evaluation is known as preemptive (or predetermined) navigation. Preemptive navigation The spec defines preemptive navigation as a mechanism for determining the target URL at Render Response, typically for a hyperlink component. The current view ID and specified outcome are used to determine the target view ID, which is then translated into a bookmarkable URL and used as the hyperlink's target. This process happens, of course, before the user has activated the component (i.e., click on the hyperlink). In fact, the user may never activate the component. The idea is to marry the declarative (or implicit) navigation model with the support for generating bookmarkable links. Based on what was just described, you should now understand why you declare the target view ID in an attribute named outcome on the new bookmarkable component tags (and why those components inherit from a component class named UIOutcomeTarget). You are not targeting a view ID directly, but rather a navigation outcome which may be interpreted as a view ID if the matching falls through to implicit navigation. Let's consider an example. Assume that you want to create a link to the home page of the application. You could define the link using one the new bookmarkable link component: This definition would match the following navigation case if it existed: * home /home.xhtml Of course, with implicit navigation available, this navigation case would be redundant. We could exclude it and the result would be the same. Home But if the target view ID depends on the context, such as the user's credentials, you might choose to reintroduce the navigation case to leverage conditional logic as we did earlier. In either case, the key is that the target view ID is not hard-coded in the template. As it turns out, you've already been using preemptive navigation when you explored bookmarkability in the last article. But there's a critical part of preemptive navigation that we haven't yet fully explored: the assembly of the query string. As it turns out, this topic also applies to redirect navigation rules. In a sense, preemptive navigation has the same semantics as redirect navigation rules because both produces URL that lead to a non-faces request. The only difference is that a bookmarkable URL is a deferred request, whereas a redirect happens immediately. In both cases, the payload in the query string is an essential part of the URLs identity. Building the query string As a result of the new GET support in JSF 2, there are now a plethora of ways to tack on values to the query string. Options can collide when heading into the navigation funnel. What comes out on the other side? There's a simple conflict resolution algorithm to find out. Each parameter source is given a precedence. When a conflict occurs, meaning two sources define the same parameter name, the parameter from the source with the highest precedence is used. The query string parameters are sourced using the following order of precedence, from highest to lowest: Implicit query string parameter (e.g., /blog.xhtml?id=3) View parameter (defined in the of the target view ID) Nested in UIOutcomeTarget (e.g., ) or UICommand component (e.g., ) Nested within the navigation case element in faces-config.xml Granted, this appears to be a lot of options. Don't worry, we'll walk you through the cases in which you would use each option in this article. We recommend you choose a single style of providing navigation parameters that best suits your architecture and keep the others in the back of your mind, so that when an edge case comes up, you can tap into their power. In the last article, you learned that you can use view parameters to let JSF manage the query string for you. Instead of using view parameters, you could just tack on the query string yourself when building a link to a blog entry. You could even abstract the parameter away from the view and define it in the navigation case instead, but it again it presents a challenge to tooling: permalink /entry.xhtml?id=#{blog.entryId} A nested would also work here, especially if you want to centralized your parameters. In terms of navigation, the most important point to emphasize here is that you can finally add query string parameters to a redirect URL in the navigation rules. This need likely appears in your existing applications. No longer do you have to resort to using the programmatic API to issue a redirect with a query string payload. Let's consider the case of posting a comment to an entry. This example demonstrates the case when you are submitting a form and want to redirect to a bookmarkable page which displays the result of submitting the form: #{commentHandler.post} /entry.xhtml id #{blog.entryId} Note: Don't confuse with a UIViewParameter. Think of it more as a redirect parameter (the tag should probably be called not , something to address in JSF 2.1). There are now plenty of options to pass the user along with the right information. But the spec can't cover everything. That's why you can now query the navigation rule base at runtime to do with it what you like. Peeking into the navigation cases You've now seen a number of ways in which the navigation cases themselves have become more dynamic. Regardless of how dynamic they are, the fact remains that once you ship the application off for deployment, the navigation cases that you defined in faces-config.xml are set in stone. That's no longer the case in JSF 2. A new navigation handler interface, named ConfigurableNavigationhandler, has been introduced that allows you to query and make live modifications to the registered NavigationCase objects. Not that you necessarily want to make changes in production. Having a configurable navigation rule set means that you can incorporate a custom configuration scheme such as a DSL or even a fluent, type-safe navigation model from which rules can be discovered at deployment time. In short, the navigation rule set is pluggable, and it's up to you what to plug into it. NavigationCase is the model that represents a navigation case in the JSF API. When JSF starts up, the navigation cases are read from the JSF descriptor, encapsulated into NavigationCase objects and registered with the ConfigurableNavigationHandler. You can retrieve one of the registered NavigationCase objects by the action expression signature and logical outcome under which it is registered. NavigationCase case = navigationHandler.getNavigationCase( facesContext, "#{commandBoard.post}", "success"); You can also access the complete navigation rule set as a Map>, where the keys are the values. Map> cases = navigationHandler.getNavigationCases(); You can use this map to register your own navigation cases dynamically. For example, a framework might read an alternative navigation descriptor (such as Seam's pages descriptor) and contribute additional navigation cases. With an individual NavigationCase object in hand, you can either read its properties or use it to create an action or redirect URL, perhaps to feed into your own navigation handler. There are a lot of possiblities here. The slightly awkward part is how you reference this new API (ConfigurableNavigationHandler). The default NavigationHandler implementation in a standard JSF implementation must implement this interface. But you still have to cast to it when you retrieve it from the Application object, as follows: ConfigurableNavigationHandler nh = (ConfigurableNavigationHandler) FacesContext.getCurrentInstance() .getApplication().getNavigationHandler(); Obviously, something to revisit in JSF 2.1. Once you get a handle on it, the navigation model is your oyster. You can define new ways to navigate or use it to generate bookmarkable URLs in your own style. Forging ahead The JSF navigation model had the right idea in spirit, but lacked a couple of elements that would allow it to truly realize loose coupling, it's required use slowed down prototyping, and you had no control to query or modify the navigation rule set at runtime. Your going to find that in JSF 2, the navigation system is much more flexible. You could argue that it finally accomplishes its original goals. For prototype applications, you can get navigation working without touching the faces-config.xml descriptor with implicit navigation. Just use a view ID, with or without an extension, as the logical outcome and away you go. As the application matures, you can establish a clean separation between JSF and your transactional tier by using conditional navigation to select a navigation case. You can trim the number of navigation cases by defining the target view ID as a value expression and having JSF resolve the target view ID from a navigation helper bean. If the design of your application calls for bookmarkable support, you can leverage the navigation handler in its new role to produce bookmarkable URLs at render time. In JSF 2, it's a lot easier to route the user around the application. While that may be good for some applications, other applications never advance the user beyond a single page. These single page applications transform in place using Ajax and partial page updates. The next article in this series will open your eyes to how well Ajax and JSF fit together, and what new Ajax innovations made their way into the spec.
November 2, 2009
by Dan Allen
· 139,479 Views · 2 Likes
article thumbnail
JSF 2 GETs Bookmarkable URLs
JSR-314: JavaServer Faces (JSF) 2.0 demonstrates a strong evolution of the JSF framework driven by de facto standards that emerged out of the JSF community and participating vendor's products. This article, the second installment in covering JSF 2.0 features contributed by Red Hat, or which Red Hat participated in extensively, covers the new features that bring formalized GET support to a framework traditionally rooted in POST requests. The primary building blocks of this support are view parameters and a pair of UI components that produce bookmarkable hyperlinks. Both features incubated in Seam and, therefore, should be familiar to any Seam developer. They are also features for which the JSF community has passionately pleaded. Author's Note: Many thanks to Pete Muir, who played a pivotal role as technical editor of this series. Read the other parts in this article series: Part 1 - JSF 2: Seam's Other Avenue to Standardization Part 2 - JSF 2 GETs Bookmarkable URLs Part 3 - Part 4 - Part 5 - Every user session must start somewhere. JSF was designed with the expectation that the user always begins on a launch view. This view captures initial state and allows the user to indicate which action to invoke by triggering a UI event, such as clicking a button. For instance, to view a mortgage loan, the user might enter its id into a text box and then click the "Lookup" button. The assumption that this scenario is the norm is surprising since it overlooks that fact that the web was founded on the concept of a hyperlink. A hyperlink points to a resource (URI), which may already contain the original state and intent, such as to view a mortgage loan summary. There's no need to bother the user with a launch view in this case. While hyperlinks are most often used in web sites, they apply to web applications as well (see this blog entry for a discussion about the difference between a web site and a web application). Hyperlinks support reuse by serving as an exchange language in composite applications. One application can link to a resource in another application in lieu of having to duplicate its functionality. In fact, the request may be coming from a legacy application that isn't even web-based. In that case, you'll likely be plopping the user into the web application somewhere in the middle. As it turns out, this situation is quite common. When you visit a blog, do you start on the search screen to find an entry to read? Not likely. More times than not, you click on a link to view a specific blog entry. The point to take away from this discussion is that initial requests (referred to as non-faces requests in JSF) can be just as important as form submissions (faces requests), whether in a web site or web application. In the past, JSF has struggled to support the scenario cited above, placing much more emphasize on faces requests. JSF 2 rectifies this imbalance by introducing view parameters and hyperlink-producing UI components. View parameters allow the application to respond to a resource request by baking formal processing of request parameters into the JSF life cycle for both GET and POST requests. View parameters are not limited to consuming data. They are bi-directional. JSF 2 can propagate the data captured by view parameters when generating bookmarkable URLs, with complementary behavior for redirect URLs produced by redirect navigation cases. We'll start by examining view parameters, how they are defined and how they are worked into the JSF life cycle. You'll then discover how they work in tandem with the new hyperlink-producing components and the navigation handler to bring "bookmarkable" support to JSF. Introducing view parameters The API documentation describes a view parameter, represented by the javax.faces.component.UIViewParameter component class, as a declarative binding between a request parameter and a model property. The binding to the model property is expressed using an EL value expression (e.g., #{blog.entryId}). If the expression is omitted, the request parameter is bound instead to a request-scoped variable with the same name. Here's a simple example of a view parameter that maps the value of a request parameter named id to the JavaBean-style property named entryId on a managed bean named blog. Assuming the entryId property on the blog managed bean is of type long, a value of 9 will be assigned to the property when the following URL is requested: http://domain/blog/entry.jsf?id=9 But wait, there's more! The value of the request parameter is first converted and validated before being assigned to the model property. This behavior should sound familiar. That's because it mirrors the processing of form input bindings on a faces request. In a way, view parameters turn the query string into an alternative form submission. And like form inputs, view parameters are also processed during faces requests. The complete view parameter life cycle is covered later when we look at view parameter propagation Before going any further, it's important to point out that view parameters are only available when using the new View Declaration Language (VDL), a standardized version of Facelets. The primary reason is because the JSR-314 EG agreed that no new features should be made to support JSP since it's deprecated as a view handler in JSF 2. Perhaps you are thinking... Isn't this already possible? If you are savvy JSF developer, you're perhaps aware that it's already possible to map a request parameter value to a model property. The assignment is declared by referencing an element of the #{param} map in a element of a managed bean declaration. For instance, you could alternatively map the id request parameter to the blog managed bean in faces-config.xml as follows: blog com.acme.Blog entryId #{param['id']} The similiarities end there. View parameters go above and beyond this simple assignment by providing: View-oriented granularity (the property mapping in the managed bean definition is global to the application) Custom converters and/or validators (along with failure messages) Bi-directionality It's hard to say which feature is the most important, but bi-directionality is certainly the most unique. Since view parameters are a mapping to a JavaBean-style property, the value can be read from the property and propagated to the next request using either the query string or the UI component tree state (depending on the type of request). You are going to find out how useful this bi-directionality can be later on in the article. Suffice to say, while the property mapping in the managed bean definition works, it's pretty anemic. View parameters are far more adequate and robust in contrast. Pertaining to the topic in this article, view parameters are the key to bringing bookmarkable support to JSF. And since bookmarks link to specific views, so must view parameters. It's all in the view As you may have guessed, view parameters are view-oriented. That means they somehow need to be associated with one or more views (as opposed to being linked to a managed bean, for instance). Up to this point, however, there was no facility for associating extensible, non-rendering metadata with a JSF view. So the EG first had to find a place within the UI component tree to stick metadata like view parameters. That led to the introduction of the metadata facet of UIViewRoot. The next section will introduce this new facet and how it's used to host view parameters for a particular view, or even a set of views. Then we get into how view parameters get processed in the JSF life cycle. The view metadata facet View parameters provide information about how request parameters should be handled when a view is either requested or linked to. The view parameters are not rendered themselves. Therefore, we say that they are part of the view's metamodel and described using metadata. So the question is, "Where should this metadata live?" It turns out that a JSF view, which is represented at the root by the javax.faces.component.UIViewRoot component class, already accommodates some metadata. Currently, this metadata consists of string values to define settings such as the locale, render kit, and content type of the view, and method expressions that designate view-specific phase observers. For example: ... While values can be assigned to these metadata properties explicitly in Java code, more often they are assigned declaratively using corresponding attributes of the component tag. But neither UIViewRoot or it's component tag can accommodate complex metadata--that is, metadata which cannot be described by a single attribute. That's were the view metadata facet comes in. The view metadata facet is a reserved facet of UIViewRoot, named javax_faces_metadata, that can hold an arbitrarily complex branch of UI components that provide additional metadata for a view. Facets are special because they are ignored by a UI component tree traversal, requiring an imperative request to step into one of them. This aspect makes a facet an ideal candidate for tucking away some metadata for the view that can be accessed on demand. The view metadata facet looks like any other facet in the UI component tree. It must be declared as a direct descendant of within a view template as follows: ... ... Note: If you are using Facelets, you may not be familiar with the tag since it's optional in Facelets. When you add it to your template, it must be the outer-most component tag, but it does not have to be the root of the document. Since the view metadata facet is a built-in facet, and is expected to be heavily used, the alias tag was introduced as a shorthand for the formal facet definition shown above: ... ... We now have a place in the UI component tree to store metadata pertaining to the view. But why define the metadata in the view template? It's all about reuse and consistency. Describing view metadata with UI components There are two important benefits to defining the metadata within the view template. First, it circumvents introducing yet another XML file with its own schema that developers would have to learn. More importantly, it allows us to reuse the UI component infrastructure to define behavior, such as registering a custom converter or validator, or to extract common view parameters into an include template. Since we're using UI components to describe the view metadata, then it makes sense to treat the UIViewParameter like any other input component. In fact, it extends UIInput. That allows us to register custom converters and validators on a UIViewParameter without any special reservations. Here's an example: Note: Later in this series you'll learn that like input components, view parameters can enforce constraints defined by Bean Validation annotations (or XML), making the explicit validation tags such as this unnecessary. But there is one caveat to embedding the view metadata in the template. Without special provisions, extracting the metadata would require building the entire view (i.e., UI component tree). Not only would this be expensive and unnecessary if the intent is not to render the view, it could also have side effects. When the component tree is built, value expressions in Facelets tag handlers get evaluated, potentially altering the state of the system. To prevent these counteractions, the view metadata facet is given special treatment in the specification. Specifically, it must be possible to be extract and built it separately from the rest of the component tree. Earlier, I mentioned that view parameters are only available in Facelets, and not JSP, because of an executive decision. There's also a technical reason why view parameters rely on Facelets. Only Facelets can provide the necessary separation between template parsing and component tree construction that allows a template fragment to be processed in isolation. The result of this operation is a genuine UI component tree, represented by UIViewRoot, that contains only the view metadata facet and its children. For all intents and purposes, it's as though the view template only contained this one child element. Using the following logic, it's possible to retrieve the metadata for an arbitrary view at any point in time. This data mining will come in to play later when we talk about view parameter propagation. String viewId = "/your_view_id.xhtml" FacesContext ctx = FacesContext.getCurrentInstance(); ViewDeclarationLanguage vdl = ctx.getApplication().getViewHandler() .getViewDeclarationLanguage(ctx, viewId); ViewMetadata viewMetadata = vdl.getViewMetadata(ctx, viewId); UIViewRoot viewRoot = viewMetadata.createMetadataView(ctx); UIComponent metadataFacet = viewRoot.getFacet(UIViewRoot.METADATA_FACET_NAME); At this point you could retrieve the UIViewParameter components, which are children of the facet, to perhaps access the view parameter mappings. More likely, though, you'll be looking for your own custom components so you can execute custom behavior before the view is rendered (e.g., view actions). The extraction of the view metadata is very clever because, while it only builds a partial view, it still honors Facelets compositions. That means you can put your metadata into a common template and include it. Using some creative arrangement, you can apply common metadata to a pattern of views. Here's an example: ... ... You've learned that defining a view metadata facet provides the following services for JSF: Arbitrarily complex metadata, which can reuse existing component infrastructure Metadata is kept with the view, or in a shared template, instead of in an external XML file Can be extracted and processed without any side effects (idempotent) Common metadata declarations can be shared across multiple views Now that you are well versed in the view metadata facet, it's time to work out a concrete example of view parameters in practice. We'll look at how to enforce preconditions and load data on an initial request using information from the query string. Then you'll learn how that information gets propagated as the user navigates to other views. Weaving parameters into the life cycle This article has alluded several times to the use case of loading a blog entry from a URL by passing the value of the id parameter to our managed bean on an initial request. Let's allow this scenario to play out. Here's the URL the user might request coming into the site: http://domain/blog/entry.jsf?id=9 We'll start by asking what we do with the value once it is assigned to the entryId property of the blog managed bean. One approach is to load the entry lazily as soon as it's referenced in the UI. #{blog.blogEntry.title} #{blog.blogEntry.content} Here's what the managed bean would look like to support this approach: @ManagedBean(name = "blog") public class Blog { private Long entryId; private BlogEntry blogEntry; public Long getEntryId() { return entryId; } public void setEntryId(Long entryId) { this.entryId = entryId; } public BlogEntry getBlogEntry() { if (blogEntry == null) { blogEntry = blogRepository.findEntry(entryId); } return blogEntry; } } Of course, it doesn't make any sense to display an entry without an id (and could even lead to a NullPointerException). So we should really make the id request parameter required. We'll also add a message if it is missing. ... In the case a required request parameter is missing, you can display the error message using the tag. Conversion and validation failures are recorded as global messages since there's no view element with which to associate. But these preconditions still don't stop the view from being rendered if a request parameter is missing or invalid. What we need is a way to execute an initialization method that parallels an action invocation on a postback. That would allow us to get everything sorted before the user sees a response. View initialization While view parameters provide the processing steps from retrieving the request value to updating the model, they do not furnish the action invocation and navigation steps that are part of the faces request life cyle. That means you have to fall back to lazy loading the data as the view is being rendered (i.e., encoded). You are also missing a definitive point to fine tune the UI component tree programmatically before it's encoded. Fortunately, another new feature in JSF 2, system events, makes it possible to perform a series of initialization steps before view rendering begins. Systems events notify registered listeners of interesting transition points in the JSF life cycle at a much finer-grained level than phase listeners. In particular, we are interested in the PreRenderViewEvent, which is fired immediately after the component tree is built (but not yet rendered). If the word "registered" evokes dreadful memories of XML descriptors, fear not. Observing the event we are interested in is just a matter of appending one or more elements to the view metadata facet. The tag has two required attributes, type and listener. The type attribute is the name of the event to observe derived by removing the Event suffix from the end of the event class name and decaptializing the result. We are only interested in one event, preRenderView. The listener attribute is a method binding expression pointing to either a no-arguments method or a method that accepts a SystemEvent. ... We can use this method to retrieve the blog entry before the view is rendered. public void loadEntry() { blogEntry = blogRepository.findEntry(entryId); } If the entry cannot be found, you could add conditional logic to the view to display an error message: The blog entry you requested does not exist. Ideally, it would be better not to display the view at all. You can force a navigation to occur using the NavigationHandler API. public void loadEntry() { try { blogEntry = blogRepository.findEntry(entryId); } catch (NoSuchEntryException e) { FacesContext ctx = FacesContext.getCurrentInstance(); ctx.getApplication().getNavigationHandler() .handleNavigation(ctx, "#{blog.loadEntry}", "invalid"); } } The only problem is that the listener method is going to be invoked even if the view parameter could not be successfully converted, validated and assigned to the model property. Once again, there's a JSF 2 feature to the rescue. You can use the new isValidationFailed() method on FacesContext to check whether a conversion or validation failure occurred while processing the view parameters. public void loadEntry() { FacesContext ctx = FacesContext.getCurrentInstance(); if (ctx.isValidationFailed()) { ctx.getApplication().getNavigationHandler() .handleNavigation(ctx, "#{blog.loadEntry}", "invalid"); return; } // load entry } So far we have dealt with a trivial string to long conversion. But view parameters allow you to represent more complex data, as long as you have a converter that can marshal the value from (and to) a string. Let's assume that we want to allow the user to look at blog entries that fall within a range of dates. The before and after dates can be encoded into the URL as follows: /entries.jsf?after=2007-12-31&before=2009-01-01 Those values can then be converted to Date objects using the converter tag and assigned to Date properties on a managed bean as follows: We again use a PreRenderViewEvent listener to load the data before the page is rendered, in this case filtering the collection of blog entries to be displayed. Emulating the behavior of an action-oriented framework, which the previous examples have demonstrated, is one use of the PreRenderViewEvent. Another is to act as a life cycle callback for programmatically creating or tweaking the UI component tree after it is "inflated" from the view template. Perhaps you want to build part of the tree dynamically from a data structure. Accomplishing this in JSF would require "binding" a bean property to an existing UI component, declared using an EL value expression in the binding attribute of the tag. But this approach is really ugly because you have to put the tree-appending logic in either the JavaBean property getter or setter, depending on whether the view is being created or restored. The PreRenderViewEvent offers a much more definitive and self-documentating hook. As you've seen, it's finally possible to respond to a bookmarkable URL in JSF (without pain or brittle code). But, up to this point, all we've done is take, take, take. For bookmarkable support to be complete, we need to be able to create bookmarkable URLs. That brings us to the topic of parameter propagation. Push the parameters on If view parameters were only capable of accepting data sent through the query string of the URL, even considering the built-in conversion and validation they provide, they really wouldn't be all that helpful. What makes them so compelling is that they are bi-directional, meaning they are also propagated to subsequent requests, and rather transparently. The subsequent request may be a faces request, which targets the current view, or a non-faces request to a view that has view parameters, which translates into a bookmarkable URL. A request for a bookmarkable URL can come from either a link in the page or a redirect navigation event. We'll look at how view parameters get propagated in all of these cases in this section. Saved by the component tree Let's return to the blog entry view and consider what happens if we have a comment form below the post. The comment form might be defined as follows: Notice that there is no reference to the id of the blog entry in this form. Assuming that the blog entry is not stored in session scope (or a third-party conversation), how will the handler know which entry the comment should be linked? This is where view parameter propagation blends with component tree state saving. When encoding of the view (i.e., rendering) is complete, the view parameter values are tucked away in the saved state of the UI component tree. When the component tree is restored on a postback, such as when the comment form is submitted, the saved view parameter values are applied to the model. This allows view parameters to tie in nicely with the existing design of JSF. The initial state supplied to the view parameters by the URL can be maintained as long as the user interacts with the view (e.g., triggers faces requests through user interface events). You can think of view parameters as an elegant replacement for hidden form fields in this case. If the user bookmarked the URL after posting a comment, however, the reference to the blog entry would be lost. That's because after a POST request, the browser location does not contain a query string. Here's what the user would see: http://domain/blog/entry.jsf If we are following best practices, we'll want to implement the Post/Redirect/Get pattern anyway. That gives us a opportunity to repopulate the query string of the URL. In the past, this would have required an explicit call to the redirect() method of ExternalContext inside the action method. FacesContext.getCurrentInstance().getExternalContext().redirect("/entry.jsf?id=" + blog.getEntryId()); This explicit (and intrusive) call was necessary because the navigation case did not provide any way to append parameters to the query string. Now, view parameters can take care of this for us. We can tell JSF to encode the view parameters of the target view ID into the redirect URL by enabling the include-redirect-params attribute on the element. /entry.xhtml #{commentHandler.post} #{view.viewId} We'll get into navigation more in the next article in this series. Let's talk about those regular old hyperlinks in the page. We want those to be bookmarkable as well. That means the state needs to be encoded into the URL they point to. Once again, view parameters come into play. Bookmarkable links Let's now assume we want to create a bookmarkable link (permalink) to the current blog entry. You can link directly to another JSF view using the outcome attribute of the new hyperlink-producing component tags, and . These component tags are represented by the component class javax.faces.component.UIOutcomeTarget. (The reason the attribute is named outcome and not viewId will be explained in the next article. For now, just know that the value of the outcome attribute can be a view ID). Both of these component tags support encoding the view parameters into the query string of the URL as signaled by the includeViewParams attribute. Here's how the permalink is defined: The default value of includeViewParams is false. Since it's set to true, the view parameters are read in reverse and appended to the query string of the link. Here's the HTML that this component tag generated, assuming an entry id of 9: Permalink The link is produced using the new getBookmarkableURL() method on the ViewHandler API. This method calls through to the encodeBookmarkableURL() on the ExternalContext API to have the session ID token tacked on, if necessary. These methods complement the getRedirectURL() and encodeRedirectURL() methods on ViewHandler and ExternalContext, respectively. In a servlet environment, the implementations happen to be the same, but the extra methods serve as both a statement of intent and an extension point for environments where a link URL and a redirect URL are handled differently, such as a portlet. Notice that the context path of the application (/blog) is prepended to the path, the extension is changed from the view suffix (.xhtml) to the JSF servlet mapping (.jsf) and the query string contains the name and value of the view parameter read from the model. If you had used an tag, you would have had to do all of these things manually. That's exactly why the EG felt it was necessary to introduce this component. We can do one better. If the outcome attribute is absent, the current view ID is assumed. So we can shorten the tag to this: If you want the link to appear as a button, you can use the component tag instead. However, note that JavaScript is required in this case to update the browser location when the button is clicked, as you can see from the generated HTML: Permalink View parameters come in especially handy when the number of parameters to keep track of increases. For instance, let's consider the case when a user is searching for entries using a query string in a particular category and wants to paginate through the results. In this case, we are dealing with at least three parameters: Yet the link to these search results still remains as simple as the permalink to an entry: This component tag will produce HTML similar to this: Refresh What if we want to link back to the previous page? In that case, we cannot allow the view parameter named page be automatically written into the query string since that will just link us to the current page. We need an override. Fortunately, it's easy to override an encoded view parameter. You simply use the standard tag, just as you would if you were defining a new query string parameter: View parameters that are encoded into links to the current view ID are pretty intuitive. Where things get tricky is when we use view parameters on a link to a different view ID. This requires putting on your thinking cap and doing some reasoning. View parameter handoff When a request is made for a URL, and in turn a JSF view ID, the view parameters defined in that view are used to map request parameters to model properties. But when the view parameters are encoded into a bookmarkable URL, the mappings are read from the target view ID. That's why it's especially important to be able to extract the view metadata from a template without having building a full component tree, as mentioned earlier. Otherwise, you would end up building a component tree for every view that is linked to in the current view. That would be very costly. Let's consider a use case. Suppose that we want to create a link from the search results to a single entry. We would define the link as follows: #{_entry.title} #{_entry.excerpt} The question to ask yourself is this. "Are the search string, category and page offset included in the URL for the entry?". I hope you said "No". The reason is because when the URL for the entry link is built, the component tag reads the view parameter mappings defined in the /entry.xhtml template. The only parameter mapped in that template is entry id. In order to preserve the filter vector, the view parameters defined in the /entries.xhtml view need to also be in the /entry.xhtml template. Aha! Since these are shared view parameters, we should define them in a common template: We can then include that template in each view that needs to preserve these view parameters: ... Keep in mind that if the user navigates to the entry after performing a search, the URL for the entry shown in the browser's location bar will now contain the filter vector. But if you want the user to be able to return to the search filter (without using the back button), that's what you want. You can always provide a simple permalink to bookmark just the entry. Even though you are now defining view parameters in each of the views, that doesn't mean the URL will become littered with empty query string parameters when they are not in use. View parameters are only encoded (i.e., added to the query string) if the value is not null. Otherwise, there is no trace of the view parameter. You have now learned how view parameters are propagated during a postback, on a redirect and into a bookmarkable URL. The main benefit of this process is that it is transparent. You don't have to worry about each and every request parameter that comprises the state in the query string of the URL. Instead, JSF interprets the view parameter metadata defined in the template of the target view and automatically appends those name/value pairs to the URL when you activate this feature. Bookmark it View parameters serve as an alternative to storing state in the UI component tree, provide a starting point for the application, help integrate with legacy applications, assert preconditions of views, make views bookmarkable, and, with help of the new UIOutcomeTarget components or the enhancement to the redirect navigation case, produce links to those bookmarkable views. This article began by introducing you to the view metadata facet, which is a general facility for defining a view's metamodel that reuses the existing UI component infrastructure. You learned that view parameters and PreRenderViewEvent listeners are the first standard implementations of view metadata. You saw how the combination of these two features allow you to capture initial state from URL query string, validate preconditions and load data for a view all before the view is rendered. Finally, you learned how view parameter values are propagated to subsequent requests. This series continues by taking a deeper look at the navigation enhancements made in JSF 2 and explaining how those changes tie into the bookmarkability that you learned about in this article. So bookmark and check back again soon!
October 29, 2009
by Dan Allen
· 103,201 Views
article thumbnail
Understanding the NHibernate Type System
This article is taken from NHibernate in Action from Manning Publications. This article delves into the NHibernate type system. For the table of contents, the Author Forum, and other resources, go to http://www.manning.com/kuate/. It is being reproduced here by permission from Manning Publications. Manning ebooks are sold exclusively through Manning. Visit the book's page for more information. Softbound print: February 2009 | 400 pages ISBN: 1932394923 Use code "dzone30" to get 30% off any version of this book. Entities are the coarse-grained classes in a system. You usually define the features of a system in terms of the entities involved: “the user places a bid for an item” is a typical feature definition that mentions three entities - user, bid and item. In contrast, value types are the much more fine grained classes in a system, such as strings, numbers, dates and monetary amounts. These fine grained classes can be used in many places and serve many purposes; the value type string can store email address, usernames and many other things. Strings are simple value types, but it is possible (but less common) to create value types that are more complex. For example, a value type could contain several fields, like an Address. So how do we differentiate between value types and entities? From a more formal standpoint, we an say an entity is any class whose instances have their own persistent identity, and a value type is a class who’s instances do not. The entity instances may therefore be in any of the three persistent lifecycle states: transient, detached, or persistent. However, we don’t consider these lifecycle states to apply to the simpler value type instances. Furthermore, because entities have their own lifecycle, the Save() and Delete() methods of the NHibernate ISession interface will apply to them, but never to value type instances. To illustrate, lets consider Figure A. Figure A – An order entity with TotalAmount value type TotalAmount is an instance of value type Money. Because value types are completely bound to that their owning entities, TotalAmount is only saved when the Order is saved. Associations and Value Types As we said, not all value types are simple. It’s possible for value types to also define associations. For example, our Money value type could have a property called Currency that is an association to a Currency entity as shown in figure 6.1.2 Figure B – The Money value type with association to a Currency entity. If your value types have associations, they must always point to entities. The reason is that, if those associations could point from entities to value types, a value type could potentially belong to several entities, which isn’t desirable. This is one of the great things about value types; if you update a value type instance, you know that it only affects the entity that owns it. For example, changing the TotalAmount of one Order simply cannot accidentally affect others. So far we’ve talked about value types and entities from an object oriented perspective. To build a more complete picture, we shall now take a look at how the relational model sees value types and entities, and how NHibernate bridges the gap. Bridging from objects to database You may be aware that a database architect would see the world of value types and entities slightly differently to this object oriented view of things. In the database, tables represent the entities, and columns represent the values. Even join tables and lookup tables are entities. So, if all tables represent entities in the database, does that mean we have to map all tables to entities in our .NET domain model? What about those value types we wanted in our model? NHibernate provides constructs for dealing with this. For example, a many-to-many association mapping hides the intermediate association table from the application, so we don’t end up with an unwanted entity in our domain model. Similarly, a collection of value typed strings behaves like a value type from the point of view of the .NET domain model even though it’s mapped to its own table in the database. These features have their uses and can often simplify your C# code. However, over time we have become suspicious of them; these “hidden” entities often end up needing exposure in our applications as business requirements evolve. The many-to-many association table, for example, often has additional columns added as the application matures, so the relationship itself becomes an entity. You might not go far wrong if you make every database-level entity be exposed to the application as an entity class. For example, we’d be inclined to model the many-to-many association as two one-to-many associations to an intervening entity class. We’ll leave the final decision to you, and return to the topic of many-to-many entity associations later in this chapter. Mapping types So far we’ve discussed the differences between value types and entities, as seen from the object oriented and relational database perspectives. We know that mapping entities is quite straight forward – entity classes are simply always mapped to database tables using , , and mapping elements. Value types need something more, which is where mapping types enter the picture. Consider this mapping of the CaveatEmptor User and email address: In ORM, you have to worry about both .NET types and SQL data types. In the example above imagine that the Email field is a .NET string, and EMAIL column is an SQL varchar. We want to tell NHibernate know how to carry out this conversion, which is where NHibernate mapping types come in. In this case, we’ve specified the mapping type "String", which we know is appropriate for this particular conversion. The String mapping type isn’t the only one built into NHibernate; NHibernate comes with various mapping types that define default persistence strategies for primitive .NET types and certain classes, such as like DateTime. Built-in mapping types NHibernate’s built-in mapping types usually reflect the name of the .NET type they map. Sometimes you’ll have a choice of mapping types available to map a particular .NET type to the database. However, the built-in mapping types aren’t designed to perform arbitrary conversions, such as mapping a VARCHAR field value to a .NET Int32 property value. If you want this kind of functionality, you will have to define your own custom value types. We will get to that topic a little later in this chapter. We’ll now discuss the basic types; date and time, objects, large objects, and various other built-in mapping types and show you what .NET and System.Data.DbType data types they handle. DbTypes are used to infer the data provider types (hence SQL data types). .NET primitive mapping types The basic mapping types in table A map .NET primitive types to appropriate DbTypes. Table A Primitive types Mapping Type .NET Type System.Data.DbType Int16 System.Int16 DbType.Int16 Int32 System.Int32 DbType.Int32 Int64 System.Int64 DbType.Int64 Single System.Single DbType.Single Double System.Double DbType.Double Decimal System.Decimal DbType.Decimal Byte System.Byte DbType.Byte Char System.Char DbType.StringFixedLength - 1 character AnsiChar System.Char DbType.AnsiStringFixedLength - 1 character Boolean System.Boolean DbType.Boolean Guid System.Guid DbType.Guid PersistentEnum System.Enum (an enumeration) The DbType for the underlying value TrueFalse System.Boolean DbType.AnsiStringFixedLength - either 'T' or 'F' YesNo System.Boolean DbType.AnsiStringFixedLength - either 'Y' or 'N' You’ve probably noticed that your database doesn’t support some of the DbTypes listed in table A. However, ADO.NET provides a partial abstraction of vendor-specific SQL data types, allowing NHibernate to work with ANSI-standard types when executing data manipulation language (DML). For database-specific DDL generation, NHibernate translates from the ANSI-standard type to an appropriate vendor-specific type, using the built-in support for specific SQL dialects. (You usually don’t have to worry about SQL data types if you’re using NHibernate for data access and data schema definition.) NHibernate supports a number of mapping types coming from Hibernate for compatibility (useful for those coming over from Hibernate or using Hibernate tools to generate hbm.xml files). Table B lists the additional names of NHibernate mapping types. Table B Additional names of NHibernate mapping types Mapping type Additional name Binary binary Boolean boolean Byte byte Character character CultureInfo locale DateTime datetime Decimal big_decimal Double double Guid guid Int16 short Int32 int Int32 integer Int64 long Single float String string TrueFalse true_false Type class YesNo yes_no From this table, you can see that writing type="integer" or type="int" is identical to type="Int32". Note that this table contains many mapping types that will be discussed in the following sections. Date/time mapping types Table C lists NHibernate types associated with dates, times, and timestamps. In your domain model, you may choose to represent date and time data using either System.DateTime or System.TimeSpan. As they have different purposes, the choice should be easy. Table C Date and time typesExcerptOpenSourceSOAch5-6.doc Mapping Type .NET Type System.Data.DbType DateTime System.DateTime DbType.DateTime - ignores the milliseconds Ticks System.DateTime DbType.Int64 TimeSpan System.TimeSpan DbType.Int64 Timestamp System.DateTime DbType.DateTime - as specific as database supports Object mapping types All .NET types in tables A and C are value types (i.e. derived from System.ValueType). This means that they can’t be null; unless you use the .NET 2.0 Nullable structure or the Nullables add-in, as discussed in the next section. Table D lists NHibernate types for handling .NET types derived from System.Object (which can store null values). Table D Nullable object typesExcerptOpenSourceSOAch5-6.doc Mapping Type .NET Type System.Data.DbType String System.String DbType.String AnsiString System.String DbType.AnsiString This table is completed by tables E and F which also contain nullable mapping types. Large object mapping types Table E lists NHibernate types for handling binary data and large objects. Note that none of these types may be used as the type of an identifier property. Table E Binary and large object typesExcerptOpenSourceSOAch5-6.doc Mapping Type .NET Type System.Data.DbType Binary System.Byte[] DbType.Binary BinaryBlob System.Byte[] DbType.Binary StringBlob System.String DbType.String Serializable Any System.Object marked with SerializableAttribute DbType.Binary BinaryBlob and StringClob are mainly supported by SQL Server. They can have a very large size and are fully loaded in memory. This can be a performance killer if used to store very large objects. So use this feature carefully. Note that you must set the NHibernate property "prepare_sql" to "true" to enable this feature. You can find up-to-date design patterns and tips for large object usage on the NHibernate website. Various CLR mapping types Table F lists NHibernate types for various other types of the CLR that may be represented as DbType.Strings in the database. Table F Other CLR-related typesExcerptOpenSourceSOAch5-6.doc Mapping Type .NET Type System.Data.DbType CultureInfo System.Globalization.CultureInfo DbType.String - 5 chars for culture Type System.Type DbType.String holding Assembly Qualified Name Certainly, isn’t the only NHibernate mapping element that has a type attribute. Using mapping types All of the basic mapping types may appear almost anywhere in the NHibernate mapping document, on normal property, identifier property, and other mapping elements. The , , , , , and elements all define an attribute named type. (There are certain limitations on which mapping basic types may function as an identifier or discriminator type, however.) You can see how useful the built-in mapping types are in this mapping for the BillingDetails class: ... The BillingDetails class is mapped as an entity. Its discriminator, id, and Number properties are value typed, and we use the built-in NHibernate mapping types to specify the conversion strategy. It’s often not necessary to explicitly specify a built-in mapping type in the XML mapping document. For instance, if you have a property of .NET type System.String, NHibernate will discover this using reflection and select String by default. We can easily simplify the previous mapping example: .... For each of the built-in mapping types, a constant is defined by the class NHibernate. NHibernateUtil. For example, NHibernate.String represents the String mapping type. These constants are useful for query parameter binding, as discussed in more detail in chapter 8: session.CreateQuery("from Item i where i.Description like :desc") .SetParameter("desc", desc, NHibernate.String) .List(); These constants are also useful for programmatic manipulation of the NHibernate mapping metamodel, as discussed in chapter 3. Of course, NHibernate isn’t limited to the built-in mapping types; you can create your own custom mapping types for handling certain scenarios. We’ll take a look this next, and explain how the mapping type system is a central to NHibernates flexibility. Creating custom mapping types Object-oriented languages like C# make it easy to define new types by writing new classes. Indeed, this is a fundamental part of the definition of object orientation. If you were limited to the predefined built-in NHibernate mapping types when declaring properties of persistent classes, you’d lose much of C#’s expressiveness. Furthermore, your domain model implementation would be tightly coupled to the physical data model, since new type conversions would be impossible. In order to avoid that, NHibernate provides a very powerful feature called custom mapping types. NHibernate provides two user-friendly interfaces that applications may use when defining new mapping types, the first being NHibernate.UserTypes.IUserType. IUserType is suitable for most simple cases and even for some more complex problems. Let’s use it in a simple scenario. Our Bid class defines an Amount property and our Item class defines an InitialPrice property, both monetary values. So far, we’ve only used a simple System.Double to represent the value, mapped with Double to a single DbType.Double column. Suppose we wanted to support multiple currencies in our auction application and that we had to refactor the existing domain model for this change. One way to implement this change would be to add new properties to Bid and Item: AmountCurrency and InitialPriceCurrency. We would then map these new properties to additional VARCHAR columns with the built-in String mapping type. Imagine if we had currency stored in 100 places, this would be lots of changes. We hope you never use this approach! Creating an implementation of IUserType Instead, we should create a MonetaryAmount class that encapsulates both currency and amount. This is a class of the domain model and doesn’t have any dependency on NHibernate interfaces: [Serializable] public class MonetaryAmount { private readonly double value; private readonly string currency; public MonetaryAmount(double value, string currency) { this.value = value; this.currency = currency; } public double Value { get { return value; } } public string Currency { get { return currency; } } public override bool Equals(object obj) { ... } public override int GetHashCode() { ... } } We’ve also made life simpler by making MonetaryAmount an immutable class, meaning it can’t be changed after it’s instantiated. We would have to implement Equals() and GetHashCode() to complete the class - but there is nothing special to consider here aside that they must be consistent, and GetHashCode() should return mostly unique numbers. We will use this new MonetaryAmount to replace the Double, as defined on the InitialPrice property for Item. We would benefit by using this new class in other places, such as the Bid.Amount. The next challenge is in mapping our new MonetaryAmount properties to the database. Suppose we’re working with a legacy database that contains all monetary amounts in USD. Our new class means our application code is no longer restricted to a single currency, but it will take time to get the changes done by the database team. Until this happens, we’d like to store just the Amount property of MonetaryAmount to the database. Because we can’t store the currency yet, we’ll convert all Amounts to USD before we save them, and from USD when we load them. The first step to handling this is to tell NHibernate how to handle our Monetarymount type. To do this, we create a MonetaryAmountUserType class that implements the NHibernate interface IUserType. Our custom mapping type is shown in listing A. Listing A Custom mapping type for monetary amounts in USD using System; using System.Data; using NHibernate.UserTypes; public class MonetaryAmountUserType : IUserType { private static readonly NHibernate.SqlTypes.SqlType[] SQL_TYPES = { NHibernateUtil.Double.SqlType }; public NHibernate.SqlTypes.SqlType[] SqlTypes { |1 get { return SQL_TYPES; } } public Type ReturnedType { get { return typeof(MonetaryAmount); } } |2 public new bool Equals( object x, object y ) { |3 if ( object.ReferenceEquals(x,y) ) return true; if (x == null || y == null) return false; return x.Equals(y); } public object DeepCopy(object value) { return value; } |4 public bool IsMutable { get { return false; } } |5 public object NullSafeGet(IDataReader dr, string[] names, object owner){ |6 object obj = NHibernateUtil.Double.NullSafeGet(dr, names[0]); if ( obj==null ) return null; double valueInUSD = (double) obj; return new MonetaryAmount(valueInUSD, "USD"); } public void NullSafeSet(IDbCommand cmd, object obj, int index) { |7 if (obj == null) { ((IDataParameter)cmd.Parameters[index]).Value = DBNull.Value; } else { MonetaryAmount anyCurrency = (MonetaryAmount)obj; MonetaryAmount amountInUSD = MonetaryAmount.Convert( anyCurrency, "USD" ); ((IDataParameter)cmd.Parameters[index]).Value = amountInUSD.Value; } } public static MonetaryAmount Convert( MonetaryAmount m, string targetCurrency) { ... |8 } } The SqlTypes property tells NHibernate what SQL column types to use for DDL schema generation, as seen in #1. The types are subclasses of NHibernate.SqlTypes.SqlType. Notice that this property returns an array of types. An implementation of IUserType may map a single property to multiple columns, but our legacy data model only has a single Double. In #2, we can see that ReturnedType tells NHibernate what .NET type is mapped by this IUserType. The IUserType is responsible for dirty-checking property values (#3). The Equals() method compares the current property value to a previous snapshot and determines whether the property is dirty and must by saved to the database. The IUserType is also partially responsible for creating the snapshot in the first place, as shown in #4. Since MonetaryAmount is an immutable class, the DeepCopy() method returns its argument. In the case of a mutable type, it would need to return a copy of the argument to be used as the snapshot value. This method is also called when an instance of the type is written to or read from the second level cache. NHibernate can make some minor performance optimizations for immutable types. The IsMutable (#5) property tells NHibernate that this type is immutable. The NullSafeGet() method shown near #6 retrieves the property value from the ADO.NET IDataReader. You can also access the owner of the component if you need it for the conversion. All database values are in USD, so you have to convert the MonetaryAmount returned by this method before you show it to the user. In #7, the NullSafeSet() method writes the property value to the ADO.NET IDbCommand. This method takes whatever currency is set and converts it to a simple Double USD value before saving. Note that, for briefness, we haven’t provided a Convert function as shown in #8. If we were to implement it, it would have code that converts between various currencies. Mapping the InitialPrice property of Item can be done as follows: This is the simplest kind of transformation that an implementation of IUserType could perform. It takes a Value Type class and maps it to a single database column. Much more sophisticated things are possible; a custom mapping type could perform validation, it could read and write data to and from an Active Directory, or it could even retrieve persistent objects from a different NHibernate ISession for a different database. You’re limited mainly by your imagination and performance concerns! In a perfect world, we’d prefer to represent both the amount and currency of our monetary amounts in the database, so we’re not limited to storing just USD. We could still use an IUserType for this, but it’s limited; If an IUserType is mapped with more than one property, we can’t use them our HQL or Criteria queries. The NHibernate query engine wouldn’t know anything about the individual properties of MonetaryAmount. You still access the properties in your C# code (MonetaryAmount is just a regular class of the domain model, after all), but not in NHibernate queries. To allow for a custom value type with multiple properties that can be accessed in queries, we should use the ICompositeUserType interface. This interface exposes the properties of our MonetaryAmount to NHibernate. Creating an implementation of ICompositeUserType To demonstrate the flexibility of custom mapping types, we won’t have to change our MonetaryAmount domain model class at all—we change only the custom mapping type, as shown in listing B. Listing B Custom mapping type for monetary amounts in new database schemas using System; using System.Data; using NHibernate.UserTypes; public class MonetaryAmountCompositeUserType : ICompositeUserType { public Type ReturnedClass { get { return typeof(MonetaryAmount); } } public new bool Equals( object x, object y ) { if ( object.ReferenceEquals(x,y) ) return true; if (x == null || y == null) return false; return x.Equals(y); } public object DeepCopy(object value) { return value; } public bool IsMutable { get { return false; } } public object NullSafeGet(IDataReader dr, string[] names, NHibernate.Engine.ISessionImplementor session, object owner) { object obj0 = NHibernateUtil.Double.NullSafeGet(dr, names[0]); object obj1 = NHibernateUtil.String.NullSafeGet(dr, names[1]); if ( obj0==null || obj1==null ) return null; double value = (double) obj0; string currency = (string) obj1; return new MonetaryAmount(value, currency); } public void NullSafeSet(IDbCommand cmd, object obj, int index, NHibernate.Engine.ISessionImplementor session) { if (obj == null) { ((IDataParameter)cmd.Parameters[index]).Value = DBNull.Value; ((IDataParameter)cmd.Parameters[index+1]).Value = DBNull.Value; } else { MonetaryAmount amount = (MonetaryAmount)obj; ((IDataParameter)cmd.Parameters[index]).Value = amount.Value; ((IDataParameter)cmd.Parameters[index+1]).Value = amount.Currency; } } public string[] PropertyNames { |1 get { return new string[] { "Value", "Currency" }; } } public NHibernate.Type.IType[] PropertyTypes { |2 get { return new NHibernate.Type.IType[] { NHibernateUtil.Double, NHibernateUtil.String }; } } public object GetPropertyValue(object component, int property) { |3 MonetaryAmount amount = (MonetaryAmount) component; if (property == 0) return amount.Value; else return amount.Currency; } public void SetPropertyValue(object comp, int property, object value) { |4 throw new Exception("Immutable!"); } public object Assemble(object cached, |5 NHibernate.Engine.ISessionImplementor session, object owner) { return cached; } public object Disassemble(object value, |6 NHibernate.Engine.ISessionImplementor session) { return value; } } #1 shows how an implementation of ICompositeUserType has its own properties, defined by PropertyNames. Similarly, the properties each have their own type, as defined by PropertyTypes (#2). The GetPropertyValue() method, shown in #3, returns the value of an individual property of the MonetaryAmount. Since MonetaryAmount is immutable, we can’t set property values individually (see #4) This isn’t a problem because this method is optional anyway. In #5, the Assemble() method is called when an instance of the type is read from the second-level cache. The Disassemble() method is called when an instance of the type is written to the second-level cache, as shown in #6. The order of properties must be the same in the PropertyNames, PropertyTypes, and GetPropertyValues() methods. The InitialPrice property now maps to two columns, so we declare both in the mapping file. The first column stores the value; the second stores the currency of the MonetaryAmount. Note that the order of columns must match the order of properties in your type implementation: In a query, we can now refer to the Amount and Currency properties of the custom type, even though they don’t appear anywhere in the mapping document as individual properties: from Item i where i.InitialPrice.Value > 100.0 and i.InitialPrice.Currency = 'XAF' In this example we’ve expanded the buffer between the .NET object model and the SQL database schema with our custom composite type. Both representations can now handle changes more robustly. If implementing custom types seems complex, relax; you rarely need to use a custom mapping type. An alternative way to represent the MonetaryAmount class is to use a component mapping, as in section 4.4.2, “Using components.” The decision to use a custom mapping type is often a matter of taste. There are few more interfaces that can be used to implement custom types; they are introduced in the next section. Other interfaces to create custom mapping types You may find that the interfaces IUserType and ICompositeUserType do not allow you to easily add more features to your custom types. In this case, you will need to use some of the other interfaces which are in the NHibernate.UserTypes namespace: The IParameterizedType interface allows you to supply parameters to your custom type in the mapping file. This interface has a unique method: SetParameterValues(IDictionary parameters) that will be called at the initialization of your type. Here is an example of mapping providing a parameter: Euro This mapping tells the custom type to use Euro as currency if it isn’t specified. The IEnhancedUserType interface makes it possible to implement a custom type that can be marshalled to and from its string representation. This functionality allows this type to be used as identifier or discriminator type. To create a type that can be used as version, you must implement the IUserVersionType interface. The INullableUserType interface allows you to interpret non-null values in a property as null in the database. When using dynamic-insert or dynamic-update, fields identified as null will not be inserted or updated. This information may also be used when generating the where clause of the SQL command when optimistic locking is enabled. The last interface is different from the previous because it is meant to implement user defined collection types: IUserCollectionType. For more details, take a look at the implementation NHibernate.Test.UserCollection.MyListType in the source code of NHibernate. Now, let’s look at an extremely important application of custom mapping types. Nullable types are found in almost all enterprise applications. Using Nullable types With .NET 1.1, primitive types can not be null; but this is no longer the case in .NET 2.0. Let’s say that we want to add a DismissDate to the class User. As long as a user is active, its DismissDate should be null. But the System.DateTime struct can not be null. And we don’t want to use some "magic" value to represent the null state. With .NET 2.0 (and 3.5 of course), you can simply write: public class User { ... private DateTime? dismissDate; public DateTime? DismissDate { get { return dismissDate; } set { dismissDate = value; } } ... } We omit other properties and methods because we focus on the nullable property. And no change is required in the mapping. If you work with .NET 1.1, the Nullables add-in (in the NHibernateContrib package for versions prior to NHibernate 1.2.0) contains a number of custom mapping types which allow primitive types to be null. For our previous case, we can use the Nullables.NullableDateTime class: using Nullables; [Class] public class User { ... private NullableDateTime dismissDate; [Property] public NullableDateTime DismissDate { get { return dismissDate; } set { dismissDate = value; } } ... } The mapping is quite straightforward: ... It is important to note that, in the mapping, the type of DismissDate must be Nullables.NHibernate.NullableDateTimeType (from the file Nullables.NHibernate.dll). This type is a wrapper used to translate Nullables types from/to database types. But if when using the NHibernate.Mapping.Attributes library, this operation is automatic, that’s why we just had to put the attribute [Property]. The NullableDateTime type behaves exactly like System.DateTime; there are even implicit operators to easily interact with it. The Nullables library contains nullable types for most .NET primitive types supported by NHibernate. You can find more details in NHibernate documentation. Using enumerated types An enumeration (enum) is a special form of value type, which inherits from System.Enum and supplies alternate names for the values of an underlying primitive type. For example, the Comment class defines a Rating. If you recall, in our CaveatEmptor application, users are able to give other comments about other users. Instead of using a simple int property for the rating, we create an enumeration: public enum Rating { Excellent, Ok, Low } We then use this type for the Rating property of our Comment class. In the database, ratings would be represented as the type of the underlying value. In this case (and by default), it is Int32. And that’s all we have to do. We may specify type="Rating" in our mapping, but it is optional; NHibernate can use reflection to find this. One problem you might run into is using enumerations in NHibernate queries. Consider the following query in HQL that retrieves all comments rated “Low”: IQuery q = session.CreateQuery("from Comment c where c.Rating = Rating.Low"); This query doesn’t work, because NHibernate doesn’t know what to do with Rating.Low and will try to use it as a literal. We have to use a bind parameter and set the rating value for the comparison dynamically (which is what we need for other reasons most of the time): IQuery q = session.CreateQuery("from Comment c where c.Rating = :rating"); q.SetParameter("rating", Rating.Low, NHibernateUtil.Enum(typeof(Rating)); The last line in this example uses the static helper method NHibernateUtil.Enum() to define the NHibernate Type, a simple way to tell NHibernate about our enumeration mapping and how to deal with the Rating.Low value. We’ve now discussed all kinds of NHibernate mapping types: built-in mapping types, user-defined custom types, and even components. They’re all considered value types, because they map objects of value type (not entities) to the database. With a good understanding of what value types are, and how they are mapped, you can now move on to the more complex issue of collections of value typed instances.
October 8, 2009
by Alvin Ashcraft
· 69,165 Views · 1 Like
article thumbnail
JPA Performance, Don't Ignore the Database
Good Database schema design is important for performance. One of the most basic optimizations is to design your tables to take as little space on the disk as possible , this makes disk reads faster and uses less memory for query processing. Data Types You should use the smallest data types possible, especially for indexed fields. The smaller your data types, the more indexes (and data) can fit into a block of memory, the faster your queries will be. Normalization Database Normalization eliminates redundant data, which usually makes updates faster since there is less data to change. However a Normalized schema causes joins for queries, which makes queries slower, denormalization speeds retrieval. More normalized schemas are better for applications involving many transactions, less normalized are better for reporting types of applications. You should normalize your schema first, then de-normalize later. Applications often need to mix the approaches, for example use a partially normalized schema, and duplicate, or cache, selected columns from one table in another table. With JPA O/R mapping you can use the @Embedded annotation for denormalized columns to specify a persistent field whose @Embeddable type can be stored as an intrinsic part of the owning entity and share the identity of the entity. Database Normalization and Mapping Inheritance Hiearchies The Class Inheritance hierarchy shown below will be used as an example of JPA O/R mapping. In the Single table per class mapping shown below, all classes in the hierarchy are mapped to a single table in the database. This table has a discriminator column (mapped by @DiscriminatorColumn), which identifies the subclass. Advantages: This is fast for querying, no joins are required. Disadvantages: wastage of space since all inherited fields are in every row, a deep inheritance hierarchy will result in wide tables with many, some empty columns. In the Joined Subclass mapping shown below, the root of the class hierarchy is represented by a single table, and each subclass has a separate table that only contains those fields specific to that subclass. This is normalized (eliminates redundant data) which is better for storage and updates. However queries cause joins which makes queries slower especially for deep hierachies, polymorphic queries and relationships. In the Table per Class mapping (in JPA 2.0, optional in JPA 1.0), every concrete class is mapped to a table in the database and all the inherited state is repeated in that table. This is not normlalized, inherited data is repeated which wastes space. Queries for Entities of the same type are fast, however polymorphic queries cause unions which are slower. Know what SQL is executed You need to understand the SQL queries your application makes and evaluate their performance. Its a good idea to enable SQL logging, then go through a use case scenario to check the executed SQL. Logging is not part of the JPA specification, With EclipseLink you can enable logging of SQL by setting the following property in the persistence.xml file: With Hibernate you set the following property in the persistence.xml file: Basically you want to make your queries access less data, is your application retrieving more data than it needs, are queries accessing too many rows or columns? Is the database query analyzing more rows than it needs? Watch out for the following: queries which execute too often to retrieve needed data retrieving more data than needed queries which are too slow you can use EXPLAIN to see where you should add indexes With MySQL you can use the slow query log to see which queries are executing slowly, or you can use the MySQL query analyzer to see slow queries, query execution counts, and results of EXPLAIN statements. Understanding EXPLAIN For slow queries, you can precede a SELECT statement with the keyword EXPLAIN to get information about the query execution plan, which explains how it would process the SELECT, including information about how tables are joined and in which order. This helps find missing indexes early in the development process. You should index columns that are frequently used in Query WHERE, GROUP BY clauses, and columns frequently used in joins, but be aware that indexes can slow down inserts and updates. Lazy Loading and JPA With JPA many-to-one and many-to-many relationships lazy load by default, meaning they will be loaded when the entity in the relationship is accessed. Lazy loading is usually good, but if you need to access all of the "many" objects in a relationship, it will cause n+1 selects where n is the number of "many" objects. You can change the relationship to be loaded eagerly as follows : However you should be careful with eager loading which could cause SELECT statements that fetch too much data. It can cause a Cartesian product if you eagerly load entities with several related collections. If you want to override the LAZY fetch type for specific use cases, you can use Fetch Join. For example this query would eagerly load the employee addresses: In General you should lazily load relationships, test your use case scenarios, check the SQL log, and use @NameQueries with JOIN FETCH to eagerly load when needed. Partitioning The main goal of partitioning is to reduce the amount of data read for particular SQL operations so that the overall response time is reduced Vertical Partitioning splits tables with many columns into multiple tables with fewer columns, so that only certain columns are included in a particular dataset, with each partition including all rows. Horizontal Partitioning segments table rows so that distinct groups of physical row-based datasets are formed. All columns defined to a table are found in each set of partitions. An example of horizontal partitioning might be a table that contains historical data being partitioned by date. Vertical Partitioning In the example of vertical partitioning below a table that contains a number of very wide text or BLOB columns that aren't referenced often is split into two tables with the most referenced columns in one table and the seldom-referenced text or BLOB columns in another. By removing the large data columns from the table, you get a faster query response time for the more frequently accessed Customer data. Wide tables can slow down queries, so you should always ensure that all columns defined to a table are actually needed. The example below shows the JPA mapping for the tables above. The Customer data table with the more frequently accessed and smaller data types is mapped to the Customer Entity, the CustomerInfo table with the less frequently accessed and larger data types is mapped to the CustomerInfo Entity with a lazily loaded one to one relationship to the Customer. Horizontal Partitioning The major forms of horizontal partitioning are by Range, Hash, Hash Key, List, and Composite. Horizontal partitioning can make queries faster because the query optimizer knows what partitions contain the data that will satisfy a particular query and will access only those necessary partitions during query execution. Horizontal Partitioning works best for large database Applications that contain a lot of query activity that targets specific ranges of database tables. Hibernate Shards Partitioning data horizontally into "Shards" is used by google, linkedin, and others to give extreme scalability for very large amounts of data. eBay "shards" data horizontally along its primary access path. Hibernate Shards is a framework that is designed to encapsulate support for horizontal partitioning into the Hibernate Core. Caching JPA Level 2 caching avoids database access for already loaded entities, this makes reading frequently accessed unmodified entities faster, however it can give bad scalability for frequent or concurrently updated entities. You should configure L2 caching for entities that are: read often modified infrequently Not critical if stale You should also configure L2 (vendor specific) caching for maxElements, time to expire, refresh... References and More Information: JPA Best Practices presentation MySQL for Developers Article MySQL for developers presentation MySQL for developers screencast Keeping a Relational Perspective for Optimizing Java Persistence Java Persistence with Hibernate Pro EJB 3: Java Persistence API Java Persistence API 2.0: What's New ? High Performance MySQL book Pro MySQL, Chapter 6: Benchmarking and Profiling EJB 3 in Action sharding the hibernate way JPA Caching Best Practices for Large-Scale Web Sites: Lessons from eBay
August 31, 2009
by Carol McDonald
· 41,742 Views · 1 Like
article thumbnail
JPA Caching
JPA has 2 levels of caching. The first level of caching is the persistence context. The JPA Entity Manager maintains a set of Managed Entities in the Persistence Context. The Entity Manager guarantees that within a single Persistence Context, for any particular database row, there will be only one object instance. However the same entity could be managed in another User's transaction, so you should use either optimistic or pessimistic locking as explained in JPA 2.0 Concurrency and locking The code below shows that a find on a managed entity with the same id and class as another in the same persistence context , will return the same instance. @Stateless public ShoppingCartBean implements ShoppingCart { @PersistenceContext EntityManager entityManager; public OrderLine createOrderLine(Product product,Order order) { OrderLine orderLine = new OrderLine(order, product); entityManager.persist(orderLine); //Managed OrderLine orderLine2 =entityManager.find(OrderLine, orderLine.getId())); (orderLine == orderLine2) // TRUE return (orderLine); } } The diagram below shows the life cycle of an Entity in relation to the Persistent Context. The code below illustrates the life cycle of an Entity. A reference to a container managed EntityManager is injected using the persistence context annotation. A new order entity is created and the entity has the state of new. Persist is called, making this a managed entity. because it is a stateless session bean it is by default using container managed transactions , when this transaction commits , the order is made persistent in the database. When the orderline entity is returned at the end of the transaction it is a detached entity. The Persistence Context can be either Transaction Scoped-- the Persistence Context 'lives' for the length of the transaction, or Extended-- the Persistence Context spans multiple transactions. With a Transaction scoped Persistence Context, Entities are "Detached" at the end of a transaction. As shown below, to persist the changes on a detached entity, you call the EntityManager's merge() operation, which returns an updated managed entity, the entity updates will be persisted to the database at the end of the transaction. An Extended Persistence Context spans multiple transactions, and the set of Entities in the Persistence Context stay Managed. This can be useful in a work flow scenario where a "conversation" with a user spans multiple requests. The code below shows an example of a Stateful Session EJB with an Extended Persistence Context in a use case scenario to add line Items to an Order. After the Order is persisted in the createOrder method, it remains managed until the EJB remove method is called. In the addLineItem method , the Order Entity can be updated because it is managed, and the updates will be persisted at the end of the transaction. The example below contrasts updating the Order using a transaction scoped Persistence Context verses an extended Persistence context. With the transaction scoped persistence context, an Entity Manager find must be done to look up the Order, this returns a Managed Entity which can be updated. With the Extended Persistence Context the find is not necessary. The performance advantage of not doing a database read to look up the Entity, must be weighed against the disadvantages of memory consumption for caching, and the risk of cached entities being updated by another transaction. Depending on the application and the risk of contention among concurrent transactions this may or may not give better performance / scalability. JPA second level (L2) caching JPA second level (L2) caching shares entity state across various persistence contexts. JPA 1.0 did not specify support of a second level cache, however, most of the persistence providers provided support for second level cache(s). JPA 2.0 specifies support for basic cache operations with the new Cache API, which is accessible from the EntityManagerFactory, shown below: If L2 caching is enabled, entities not found in persistence context, will be loaded from L2 cache, if found. The advantages of L2 caching are: avoids database access for already loaded entities faster for reading frequently accessed unmodified entities The disadvantages of L2 caching are: memory consumption for large amount of objects Stale data for updated objects Concurrency for write (optimistic lock exception, or pessimistic lock) Bad scalability for frequent or concurrently updated entities You should configure L2 caching for entities that are: read often modified infrequently Not critical if stale You should protect any data that can be concurrently modified with a locking strategy: Must handle optimistic lock failures on flush/commit configure expiration, refresh policy to minimize lock failures The Query cache is useful for queries that are run frequently with the same parameters, for not modified tables. The EclipseLink JPA persistence provider caching Architecture The EclipseLink caching Architecture is shown below. Support for second level cache in EclipseLink is turned on by default, entities read are L2 cached. You can disable the L2 cache. EclipseLink caches entities in L2, Hibernate caches entity id and state in L2. You can configure caching by Entity type or Persistence Unit with the following configuration parameters: Cache isolation, type, size, expiration, coordination, invalidation,refreshing Coordination (cluster-messaging) Messaging: JMS, RMI, RMI-IIOP, … Mode: SYNC, SYNC+NEW, INVALIDATE, NONE The example below shows configuring the L2 cache for an entity using the @Cache annotation The Hibernate JPA persistence provider caching Architecture The Hibernate JPA persistence provider caching architecture is different than EclipseLink: it is not configured by default, it does not cache enities just id and state, and you can plug in different L2 caches. The diagram below shows the different L2 cache types that you can plug into Hibernate. The configuration of the cache depends on the type of caching plugged in. The example below shows configuring the hibernate L2 cache for an entity using the @Cache annotation For More Information: Introducing EclipseLink EclipseLink JPA User Guide Hibernate Second Level Cache Speed Up Your Hibernate Applications with Second-Level Caching Hibernate caching Java Persistence API 2.0: What's New ? Beginning Java™ EE 6 Platform with GlassFish™ 3 Pro EJB 3: Java Persistence API (JPA 1.0)
August 24, 2009
by Carol McDonald
· 80,818 Views · 39 Likes
article thumbnail
Using SelfPopulatingCache in Ehcache
Often you will notice that Ehcache is used mostly like a tool that implements highly configurable maps. Sometimes developers configure time-to-live properties, or make use of disk-store functionality, but you can rarely meet someone who has cache population/eviction process that makes sense. In the perfect world I would expect cache to be a universal pool. I request a value for a key and would like to get it whenever it is possible and as fast as possible with just one line of code. But in reality I usually can see huge cache population code on the application startup, daemon threads that update caches in eternal loop and numerous “ifs” around cache.get() calls. In my strive to the perfect world I’ve discovered a SelfPopulatingCache class in Ehcache. In this article I will describe how using SelfPopulatingCache class one can implement a cache with self creating objects with optional auto-updating. In some way this example is an implementation of ideas mentioned in Ehcache documentation. Example What you will see down here: A Reader that fetches an object from cache 5 times every 0.5 seconds. Behind scenes cache will create a new object if there is no such object is there in cache for a key requested. A daemon thread will trigger cache refresh every 2 seconds. The most important class in this example is ExampleCacheProvider. package com.blogspot.mikler.java; import net.sf.ehcache.CacheManager; import net.sf.ehcache.Ehcache; import net.sf.ehcache.constructs.blocking.SelfPopulatingCache; import net.sf.ehcache.constructs.blocking.CacheEntryFactory; public class ExampleCacheProvider { private CacheManager cacheManager; private CacheEntryFactory updatingFactory; public SelfPopulatingCache selfPopulatingCache; public ExampleCacheProvider() throws Exception { cacheManager = CacheManager.create(); Ehcache originalCache = cacheManager.getCache("com.blogspot.mikler.java.cache"); final String cacheType = System.getProperty("com.blogspot.mikler.java.cache.factory"); if (cacheType == null || cacheType.equals("create")){ updatingFactory = new ExampleCacheEntryFactory(); } else { updatingFactory = new ExampleUpdatingCacheEntryFactory(); } selfPopulatingCache = new SelfPopulatingCache(originalCache, updatingFactory); //chache refresh thread Thread updatingThread = new Thread(){ public void run() { while (true){ System.out.println("!!!!! Doing refresh !!!!!"); selfPopulatingCache.refresh(); try { Thread.sleep(2000); } catch (InterruptedException e) { System.out.println("Interrupted"); } } } }; updatingThread.setDaemon(true); updatingThread.start(); } public Ehcache getCache(){ return selfPopulatingCache; } } What it does is creating simple Ehcache (original cache) and wrapping it with SelfPopulatingCache (selfPopulatingCache). We can use this class the same way as CacheManager, so one can consider extending CacheManager, but to keep it simple here we'll stick to this kind of cache source. While wrapping we specify updatingFactory, which can be set to one of two options: ExampleCacheEntryFactory (line 19) and ExampleUpdatingCacheEntryFactory(line 21). For the purposes of this example the choice between this two options is done based on the “com.blogspot.mikler.java.cache.factory” system property value. The difference between this two is that ExampleCacheEntryFactory implements CacheEntryFactory interface, while ExampleUpdatingCacheEntryFactory extends ExampleCacheEntryFactory and implements UpdatingCacheEntryFactory. The difference between using each of this options is explained later on. Meanwhile here is the code of both classes. package com.blogspot.mikler.java; import net.sf.ehcache.constructs.blocking.CacheEntryFactory; public class ExampleCacheEntryFactory implements CacheEntryFactory { public Object createEntry(Object key) throws Exception { System.out.println("++++++creating entry for key = " + key); return new StringBuffer(Long.toString(Math.round(100*Math.random())) + key+"0"); } } package com.blogspot.mikler.java; import net.sf.ehcache.constructs.blocking.UpdatingCacheEntryFactory; public class ExampleUpdatingCacheEntryFactory extends ExampleCacheEntryFactory implements UpdatingCacheEntryFactory { public void updateEntryValue(Object key, Object value) throws Exception { System.out.println("~~~~~~UPDATING entry for key = " + key); final StringBuffer stringBuffer = (StringBuffer) value; stringBuffer.append(stringBuffer.length()); } } As you can see in this example as cache element’s key string used, while StringBuffer is used as a value. In createEntry() method in ExampleCacheEntryFactory StringBuffer is created with leading random number. While in updateEntryValue() method of ExampleUpdatingCacheEntryFactory existing StringBuffer length is appended to the buffer itself. And finally, here goes our Reader main class. It fetches our wrapped cache, get’s value for “foo” key from it and stores it into final local variable fooOriginalBuffer, that is never changed late in Reader’s code. Then it starts doing 5 iterations of getting value for “foo” key from cache, displaying debug info and stats, and sleeping for one second. The code is simple as this. package com.blogspot.mikler.java; import net.sf.ehcache.Ehcache; public class Reader { private ExampleCacheProvider exampleCacheProvider; public Reader(ExampleCacheProvider exampleCacheProvider) { this.exampleCacheProvider = exampleCacheProvider; } public void run(){ Ehcache cache = exampleCacheProvider.getCache(); final StringBuffer fooOriginalBuffer = (StringBuffer) cache.get("foo").getValue(); for (int i = 0; i < 5; i++){ System.out.println("----------------------------------"); System.out.println("Starting iteration " + i); StringBuffer fooBuffer = (StringBuffer) cache.get("foo").getValue(); System.out.println("fooBuffer. = " + fooBuffer.toString()); System.out.println("fooOriginalBuffer = " + fooOriginalBuffer.toString()); System.out.println("cache.getSize() = " + cache.getSize()); System.out.println("----------------------------------"); try { Thread.sleep(1000); } catch (InterruptedException e) { System.out.println("Interrupted"); } } } public static void main(String[] args) throws Exception { ExampleCacheProvider cacheProvider = new ExampleCacheProvider(); Reader reader = new Reader(cacheProvider); reader.run(); } } Let’s run it with both updatingFactory options. Output of running the Reader with ExampleCacheEntryFactory (-Dcom.blogspot.mikler.java.cache.factory=create) !!!!! Doing refresh !!!!! ++++++creating entry for key = foo ---------------------------------- Starting iteration 0 fooBuffer. = 35foo0 fooOriginalBuffer = 35foo0 cache.getSize() = 1 ---------------------------------- ---------------------------------- Starting iteration 1 fooBuffer. = 35foo0 fooOriginalBuffer = 35foo0 cache.getSize() = 1 ---------------------------------- !!!!! Doing refresh !!!!! ++++++creating entry for key = foo ---------------------------------- Starting iteration 2 fooBuffer. = 36foo0 fooOriginalBuffer = 35foo0 cache.getSize() = 1 ---------------------------------- ---------------------------------- Starting iteration 3 fooBuffer. = 36foo0 fooOriginalBuffer = 35foo0 cache.getSize() = 1 ---------------------------------- !!!!! Doing refresh !!!!! ++++++creating entry for key = foo ---------------------------------- Starting iteration 4 fooBuffer. = 51foo0 fooOriginalBuffer = 35foo0 cache.getSize() = 1 ---------------------------------- And here how the output looks like while running Reader with ExampleUpdatingCacheEntryFactory as updatingFactory (-Dcom.blogspot.mikler.java.cache.factory=update) !!!!! Doing refresh !!!!! ++++++creating entry for key = foo ---------------------------------- Starting iteration 0 fooBuffer. = 19foo0 fooOriginalBuffer = 19foo0 cache.getSize() = 1 ---------------------------------- ---------------------------------- Starting iteration 1 fooBuffer. = 19foo0 fooOriginalBuffer = 19foo0 cache.getSize() = 1 ---------------------------------- !!!!! Doing refresh !!!!! ~~~~~~UPDATING entry for key = foo ---------------------------------- Starting iteration 2 fooBuffer. = 19foo06 fooOriginalBuffer = 19foo06 cache.getSize() = 1 ---------------------------------- ---------------------------------- Starting iteration 3 fooBuffer. = 19foo06 fooOriginalBuffer = 19foo06 cache.getSize() = 1 ---------------------------------- !!!!! Doing refresh !!!!! ~~~~~~UPDATING entry for key = foo ---------------------------------- Starting iteration 4 fooBuffer. = 19foo067 fooOriginalBuffer = 19foo067 cache.getSize() = 1 ---------------------------------- Conclusion As you can see the output is quite different and here are some conclusions we come to from analyzing it: No NullPointerException is occurs while trying to get object from cache that is not there. It is being created in both cases. If updatingFactory is instance of CacheEntryFactory (ExampleCacheEntryFactory in our case) when cache.refresh() is called each object in cache is being recreated. Also when updatingFactory is instance of CacheEntryFactory final fooOriginalBuffer variable is not updated. Meanwhile in case when updatingFactory is instance of CacheEntryFactory (UpdatingCacheEntryFactory in our case) when cache.refresh() is called each object in cache gets updated instead of being recreated. And final fooOriginalBuffer variable value is updated as well. (Actually this variable itself is passed to updateEntryValue() method of ExampleUpdatingCacheEntryFactory) Instructions about how to check out the source code for this article you can find in the original post. Originally posted on miklerjava.blogspot.com
August 17, 2009
by Mikhail Kolesnik
· 29,789 Views
article thumbnail
JPA 2.0 Concurrency and Locking
Optimistic locking lets concurrent transactions process simultaneously, but detects and prevent collisions, this works best for applications where most concurrent transactions do not conflict. JPA Optimistic locking allows anyone to read and update an entity, however a version check is made upon commit and an exception is thrown if the version was updated in the database since the entity was read. In JPA for Optimistic locking you annotate an attribute with @Version as shown below: public class Employee { @ID int id; @Version int version; The Version attribute will be incremented with a successful commit. The Version attribute can be an int, short, long, or timestamp. This results in SQL like the following: “UPDATE Employee SET ..., version = version + 1 WHERE id = ? AND version = readVersion” The advantages of optimistic locking are that no database locks are held which can give better scalability. The disadvantages are that the user or application must refresh and retry failed updates. Optimistic Locking Example In the optimistic locking example below, 2 concurrent transactions are updating employee e1. The transaction on the left commits first causing the e1 version attribute to be incremented with the update. The transaction on the right throws an OptimisticLockException because the e1 version attribute is higher than when e1 was read, causing the transaction to roll back. Additional Locking with JPA Entity Locking APIs With JPA it is possible to lock an entity, this allows you to control when, where and which kind of locking to use. JPA 1.0 only supported Optimistic read or Optimistic write locking. JPA 2.0 supports Optimistic and Pessimistic locking, this is layered on top of @Version checking described above. JPA 2.0 LockMode values : OPTIMISTIC (JPA 1.0 READ): perform a version check on locked Entity before commit, throw an OptimisticLockException if Entity version mismatch. OPTIMISTIC_FORCE_INCREMENT (JPA 1.0 WRITE) perform a version check on locked Entity before commit, throw an OptimisticLockException if Entity version mismatch, force an increment to the version at the end of the transaction, even if the entity is not modified. PESSIMISTIC: lock the database row when reading PESSIMISTIC_FORCE_INCREMENT lock the database row when reading, force an increment to the version at the end of the transaction, even if the entity is not modified. There are multiple APIs to specify locking an Entity: EntityManager methods: lock, find, refresh Query methods: setLockMode NamedQuery annotation: lockMode element OPTIMISTIC (READ) LockMode Example In the optimistic locking example below, transaction1 on the left updates the department name for dep , which causes dep's version attribute to be incremented. Transaction2 on the right gives an employee a raise if he's in the "Eng" department. Version checking on the employee attribute would not throw an exception in this example since it was the dep Version attribute that was updated in transaction1. In this example the employee change should not commit if the department was changed after reading, so an OPTIMISTIC lock is used : em.lock(dep, OPTIMISTIC). This will cause a version check on the dep Entity before committing transaction2 which will throw an OptimisticLockException because the dep version attribute is higher than when dep was read, causing the transaction to roll back. OPTIMISTIC_FORCE_INCREMENT (write) LockMode Example In the OPTIMISTIC_FORCE_INCREMENT locking example below, transaction2 on the right wants to be sure that the dep name does not change during the transaction, so transaction2 locks the dep Entity em.lock(dep, OPTIMISTIC_FORCE_INCREMENT) and then calls em.flush() which causes dep's version attribute to be incremented in the database. This will cause any parallel updates to dep to throw an OptimisticLockException and roll back. In transaction1 on the left at commit time when the dep version attribute is checked and found to be stale, an OptimisticLockException is thrown Pessimistic Concurrency Pessimistic concurrency locks the database row when data is read, this is the equivalent of a (SELECT . . . FOR UPDATE [NOWAIT]) . Pessimistic locking ensures that transactions do not update the same entity at the same time, which can simplify application code, but it limits concurrent access to the data which can cause bad scalability and may cause deadlocks. Pessimistic locking is better for applications with a higher risk of contention among concurrent transactions. The examples below show: reading an entity and then locking it later reading an entity with a lock reading an entity, then later refreshing it with a lock The Trade-offs are the longer you hold the lock the greater the risks of bad scalability and deadlocks. The later you lock the greater the risk of stale data, which can then cause an optimistic lock exception, if the entity was updated after reading but before locking. The right locking approach depends on your application: what is the risk of risk of contention among concurrent transactions? What are the requirements for scalability? What are the requirements for user re-trying on failure? For More Information: Preventing Non-Repeatable Reads in JPA Using EclipseLink Java Persistence API 2.0: What's New ? What's New and Exciting in JPA 2.0 Beginning Java™ EE 6 Platform with GlassFish™ 3 Pro EJB 3: Java Persistence API (JPA 1.0)
August 3, 2009
by Carol McDonald
· 51,403 Views · 1 Like
article thumbnail
Hibernate Performance Tuning
Hibernate is a powerful, high performance object/relational persistence and query service. Hibernate lets you develop persistent classes following object-oriented idiom - including association, inheritance, polymorphism, composition, and collections. Hibernate allows you to express queries in its own portable SQL extension (HQL), as well as in native SQL, or with an object-oriented Criteria and Example API. Quintessential to using any ORM framework like hibernate is to know how to leverage the various performance tuning methods supported by the framework. In this volume Wings Jiang discusses three performance tuning strategies for hibernate: SQL Optimization Session Management Data Caching SQL Optimization When using Hibernate in your application, you already have been coding HQL (Hibernate Query Language) somewhere. For example, “from User user where user.name = ‘John’”. If issuing your SQL statement like this, Hibernate cannot use the SQL cache implemented by database because name of the user, in most scenarios, is extremely distinct. On the contrary, while using placeholder to achieve this, like “from User user where user.name =?” will be cached by the Database to fulfill the performance improvement. You can also set some Hibernate properties to improve performance, such as setting the number of records retrieved while fetching records via configuring property hibernate.jdbc.fetch_size, setting the batch size when committing the batch processing via configuring property hibernate.jdbc.batch_size and switching off the SQL output via setting property hibernate.show_sql to false in product environments. In addition, the performance tuning of your target Database is also significant, like SQL clauses tuning, reasonable indexes, delicate table structures, data partitions etc. Session Management Undoubtedly, Session is the pith of Hibernate. It manages the Database related attributes, such as JDBC connections, data entities’ states. Managing the Session efficiently is the key to getting high performance in enterprise applications. One of the many commonly used and equally elegant approaches to session management in hibernate is to use ThreadLocal. Threadlocal will create a local copy of session for every thread. Thus synchronization problems are averted, when objects are put in the Threadlocal, . To understand how ThreadLocal variables are used in Java, refer to Sun Java Documentation at http://java.sun.com/j2se/1.5.0/docs/api/java/lang/ThreadLocal.html Data Caching Before accomplishing any data caching, it is essential to set the property hibernate.cache.user_query_cache = true. There are three kinds of commonly used Caching Strategies in Hibernate: Using cache based on Session level (aka Transaction layer level cache). This is also called first-level cache. Using cache based on SessionFactory level (Application layer level cache). This is also called second-level cache. Using cluster cache which is employed in distributed application (in different JVMs). In fact, some techniques, like loading data by id, lazy initialization which betokens loading appropriate data in proper time rather than obtaining a titanic number of useless records, which are fairly useless in the subsequent operations are consummated via data caching. First Level Cache (aka Transaction layer level cache) Fetching an object from database always has a cost associated with it. This can be offset by storing the entities in hibernate session. Next time the entities are required, they are fetched from the session, rather than fetching from the database. To clear an object from the session use: session.evict(object). To clear all the objects from the session use session.clear(). Second Level Cache (aka Application layer level cache) In this approach, if an object is not found in session, it is searched for in the session factory before querying the database for the object. If an object is indeed fetched from database, the selected data should be put in session cache. This would improve the performance when the object is required next time. To remove an entity from session factory use the various overloaded implementations of evict() method of SessionFactory. In fact, Hibernate lets you tailor your own caching implementation by specifying the name of a class that implements org.hibernate.cache.CacheProvider using the property hibernate.cache.provider_class. But it is recommended to employ a few built-in integrations with open source cache providers (listed below). Cache Type Cluster Safe Query Cache Supported Hashtable Memory NO YES EHCache Memory, Disk NO YES OSCache Memory, Disk NO YES SwarmCache Clustered YES (clustered invalidation) NO JBoss TreeCache Clustered YES (replication) YES Terracota Clustered YES YES In order to use second level caching, developers have to append some configurations in hibernate.cfg.xml (for example, using EHCache here). net.sf.ehcache.hibernate.Provider In addition, developers also need to create a cache specific configuration file (Example: ehcache.xml for EHCache). (1) diskStore : Sets the path to the directory where cache .data files are created. The following properties are translated: a.user.home - User's home directory b.user.dir - User's current working directory c.java.io.tmpdir (Default temp file path) maxElementsInMemory : Sets the maximum number of objects that will be created in memory. eternal : Sets whether elements are eternal. If eternal, timeouts are ignored and the element is never expired. timeToIdleSeconds : Sets the time to idle for an element before it expires. Is only used if the element is not eternal. Idle time is now - last accessed time. timeToLiveSeconds : Sets the time to live for an element before it expires. Is only used if the element is not eternal. TTL is now - creation time overflowToDisk : Sets whether elements can overflow to disk when the in-memory cache has reached the maxInMemory limit. Finally the cache concurrency strategy has to be specified in mapping files. For example, the following code fragment shows how to configure your cache strategy. … … Cache Concurrency Strategies There are four kinds of built-in cache concurrency strategies provided by Hibernate. Chosing a right concurrency strategy for your hibernate implementation is the key to cache performance optimization. Besides to ensure data consistency and transaction integrity it is indispensable to master these strategies. read-only If your application needs to read but never modify instances of a persistent class, a read-only cache may be used. This is the simplest and best performing strategy. It's even perfectly safe for use in a cluster. nonstrict-read-write If the application only occasionally needs to update data (For example, if it is extremely unlikely that two transactions would try to update the same item simultaneously) and strict transaction isolation is not required, a nonstrict-read-write cache might be appropriate. read-write If the application needs to update data, a read-write cache might be appropriate. This cache strategy should never be used if serializable transaction isolation level is required. transactional If the application seldom needs to update data and at the same time, application also needs to avoid “dirty read” and “repeatable read”, this kind of concurrency strategy can be employed. The transactional cache strategy provides support for fully transactional cache providers such as JBoss TreeCache. The following table lists cache concurrency strategy supported by various cache providers. Cache Read-only Nonstrict-read-write Read-write Transactional Hashtable YES YES YES N/A EHCache YES YES YES N/A OSCache YES YES YES N/A SwarmCache YES YES N/A N/A JBoss TreeCache YES N/A N/A YES Cluster Cache (in different JVMs) Hibernate also supports cluster caching in disparate JVMs. At present, both SwarmCache and JBoss TreeCache support cluster caching across multiple JVMs. In some situations, especially at the level of enterprise, certain application has to support the concurrency accessing of thousands of users, at that time, cluster cache can help you because the cluster can provide failover and load balancing which improve the performance of application. Points to Note When employing one of the four cache strategies above, pay close attention to the following situation: Data cached almost immutable If data you want to cache is almost constant, you can use data caching which can improve the performance of the application. On the contrary, if the caching data are quiet volatile, Hibernate have to maintain and update the caching over time which extremely leads to performance hit. Data sizes in reasonable range If the size of data you is caching is massive, Hibernate will occupy the most memories of system, which causes the long waiting time of the whole application. Low frequency of data updating If data you are caching needs to be modified frequently, Hibernate have to take an array of time to update and modify the data in caching, which impacts the performance of the application as well. High frequency of data querying If data you are caching is steady, which means that most of the operations are querying, searching, no updating and modifying, making the most use of caching will be affording huge performance improvement. None crucial data Because of existing some incongruities when keeping the data in caching, so if the data you are caching is fairly crucial, do not use caching. By contrast, if the data in caching is insignificant, just use it without any vacillation. Summary Actually, after employing SQL Optimization, Session Management, Data Caching, we will obtain great battalions of performance gains, which make applications achieve acceptable waiting time for the final customers. External Links for Further Study http://www.hibernate.org/hib_docs/reference/en/html/performance.html http://blogs.jboss.com/blog/acoliver/2006/01/23/Hibernate_EJB3_Tuning.txt About Author I am Wings Jiang from BCM China. I have mainly focused on J2EE technologies in recent years and worked in several projects involving Struts/Tapestry, Spring, Hibernate, WebLogic, Websphere, Oracle, DB2 etc. I have experience in design and code of several Java applications. Hibernate performance is one of the areas I pay close heed to in my current working.
June 10, 2009
by Ming Jiang
· 141,805 Views · 4 Likes
article thumbnail
JavaFX: Using Patterns & Clean Code
We are seeing quite a number of exciting JavaFX demos around, demonstrating the pretty features of the language and the capability of easily integrating cool graphics. But, as a software designer, I can't prevent myself from seeing that in most examples we see bloated code - no good separation of concerns and poor applications of the MVC pattern. This is reasonable, as JavaFX was a new language and people needed first to be taught about the syntax and features; but now that - I presume - many of us have been introduced with the new language, it's high time we started worrying about good practices, as well as writing self-commenting code. Let's remember that good practices and good design are always more important than the language! So, let's introduce a very simple project - a Contact List whose specifications are: We have a list of "contacts", where each item is name, last name, email, phone, etc... The UI shows a list of contacts, that can be filtered by a text field; if you enter a value in it, only the contacts whose name starts with the entered text are shown. Selections are applied as you type. Selecting an item in the list of contacts, the details are shown in a form, where you can edit them. At any selection change, the form is animated (a rotation and a blur effect). You can get the code from: svn co -r 37 https://kenai.com/svn/javafxstuff~svn/trunk/ContactList/src/ContactList The model Let's first have a quick look at the model classes. First a simple value object representing a piece of data: package it.tidalwave.javafxstuff.contactlist.model; public class Contact { public var id: String; public var firstName: String; public var lastName: String; public var phone: String; public var email: String; public var photo: String; override function toString() { return "\{id: {id}, value: {firstName} {lastName}, phone: {phone}, email: {email}" } } Then a small service which provides a bunch of data: package it.tidalwave.javafxstuff.contactlist.model; public abstract class ContactRegistry { public abstract function items() : Contact[]; } In the demo code, you'll find a mock implementation with some wired values; in a real case this could be a Business Delegate encapsulating code for retrieving data remotely. So far, so good - it's pretty normal to keep these things separated from the UI. The Controllers We're not going to see a classic Controller here; actually, we're slightly departing from the "pure" MVC. The code I'm showing you is more a "Presentation Model", a pattern described by Martin Fowler as: The essence of a Presentation Model is of a fully self-contained class that represents all the data and behavior of the UI window, but without any of the controls used to render that UI on the screen. A view then simply projects the state of the presentation model onto the glass. This class is basically an hybrid between a classic model and a controller. It is also a façade between the view and the domain model. package it.tidalwave.javafxstuff.contactlist.model; import it.tidalwave.javafxstuff.contactlist.model.ContactRegistry; import it.tidalwave.javafxstuff.contactlist.model.ContactRegistryMock; public class PresentationModel { public var searchText : String; public var selectedIndex : Integer; // The Business Delegate def contactRegistry = ContactRegistryMock{} as ContactRegistry; def allContacts = bind contactRegistry.items(); // The contacts filtered according the contents of the search field public-read def contacts = bind allContacts[contact | "{contact.firstName} {contact.lastName}".startsWith(searchText)]; // The selected contact; the code also triggers a notification at each change public-read def selectedContact = bind contacts[selectedIndex] on replace previousContact { onSelectedContactChange(); }; // Notifies a change in the current Contact selection public-init var onSelectedContactChange = function() { } } Note the extreme compactness brought by functional programming. There's almost no imperative programming as everything is achieved by properly using the binding feature. The only imperative part is the 'onSelectedContactChange' function, which is just a listener to notify selection changes to some external code - it will be used only for triggering the animation. BTW, I'd like to remove it from here, but I wasn't able to. Maybe it's a JavaFX thing that I've not understood yet, but I'm keeping it for another post. Now, everything about the animation goes encapsulated in a specific class, which only exposes two properties controlling the animation: the effect and the rotation angle. A single play() function is provided to start the animation. package it.tidalwave.javafxstuff.contactlist.view; import javafx.animation.Interpolator; import javafx.animation.Timeline; import javafx.scene.effect.GaussianBlur; public class AnimationController { public-read var rotation = 0; public-read def effect = GaussianBlur{} def timeline = Timeline { repeatCount: 1 keyFrames: [ at(0s) { effect.radius => 20; rotation => 45 } at(300ms) { effect.radius => 0 tween Interpolator.EASEBOTH; rotation => 0 tween Interpolator.EASEBOTH } ] } public function play() { timeline.playFromStart(); } } The Views Now, a UI component. The way we design it largely depends on the process, as a graphic designer could be involved. In any case, I think that the whole UI should not be implemented in a single, bloated class; rather relevant pieces should be split apart. For instance, a CustomNode can model the "form" that renders the contact details (in the code below I've omitted all the attributes related to rendering): package it.tidalwave.javafxstuff.contactlist.view; import javafx.scene.CustomNode; import javafx.scene.Group; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; import javafx.scene.Node; import javafx.ext.swing.SwingLabel; import javafx.ext.swing.SwingTextField; import it.tidalwave.javafxstuff.contactlist.model.Contact; public class ContactView extends CustomNode { public var contact : Contact; public override function create() : Node { return Group { content: [ VBox { content: [ SwingLabel { text: bind "{contact.firstName} {contact.lastName}" } HBox { content: [ SwingLabel { text: "First name: " } SwingTextField { text: bind contact.firstName } ] } HBox { content: [ SwingLabel { text: "Last name: " } SwingTextField { text: bind contact.lastName } ] } HBox { content: [ SwingLabel { text: "Email: " } SwingTextField { text: bind contact.email } ] } HBox { content: [ SwingLabel { text: "Phone: " } SwingTextField { text: bind contact.phone } ] } ] } ] }; } } As you can see, we have only layout and data binding here, the only things a view should do. Putting all together Now the last piece of code, the Main, which builds up the application (again, I've omitted all attributes only related to rendering): package it.tidalwave.javafxstuff.contactlist.view; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; import javafx.scene.Scene; import javafx.stage.Stage; import javafx.ext.swing.SwingLabel; import javafx.ext.swing.SwingList; import javafx.ext.swing.SwingListItem; import javafx.ext.swing.SwingTextField; import it.tidalwave.javafxstuff.contactlist.controller.PresentationModel; Stage { def animationController = AnimationController{}; def presentationModel = PresentationModel { onSelectedContactChange : function() { animationController.play(); } }; scene: Scene { content: VBox { content: [ HBox { content: SwingLabel { text: "Contact List" } } HBox { content: [ SwingLabel { text: "Search: " } SwingTextField { text: bind presentationModel.searchText with inverse } ] } HBox { content: [ SwingList { items: bind for (contact in presentationModel.contacts) { SwingListItem { text:"{contact.firstName} {contact.lastName}" } } selectedIndex: bind presentationModel.selectedIndex with inverse } ContactView { contact: bind presentationModel.selectedContact effect: bind animationController.effect rotate: bind animationController.rotation } ] } ] } } } As in the previous code snippets, I think the listing can be easily read and understood. Basically, we are glueing all the pieces together and binding the relevant models. In the end, each class in this small project does a simple, cohese thing: representing data, encapsulating the presentation logic, controlling the animation, rendering the views. Dependencies are reduced to the minimum and they have the correct direction: views depend on the models (and not the opposite) and the AnimationController; the AnimationController is independent. You could replace the view components without affecting the rest of the classes, as well as removing or adding other animations by properly using different AnimationControllers. This good separation of roles and responsibilities is the good way to apply OO. There is a detail which is worth discussing. Note the two bind ... with inverse. They implement the so-called "bidirectional binding" where not only a change in the model (e.g. PresentationModel.selectedIndex) is reflected to attributes in the UI (e.g. SwingList.selectedIndex), but also the opposite happens. Indeed, the reverse binding is more important in our example, because it implements the controller responsibility (it captures user's gestures from the view and changes the model); the direct binding from the PresentationModel to SwingList, instead, is useless, as in our case the PresentationModel is never the originator of a change. So, why not using a simple, direct binding in PresentationModel towards SwingList? Such as: public class PresentationModel { var list : SwingList; public def selectedIndex = bind list.selectedIndex; ... } Because this would introduce a dependency from the model/controller to the view, which is plain wrong. Here, bind ... with inverse not only works as a shortcut for writing less code (that is, explicitly declaring a binding and its inverse), but it's also an essential feature for a better design. As far as I know - but I could be wrong - for example in ActionScript (Adobe Flex language) there's no bidirectional binding (you need to put binding keywords at both ends of the association), thus introducing unneeded or circular dependencies. I believe this is true at least at code level (as far as I understand, there are different ways to do binding in ActionScript).
May 12, 2009
by Fabrizio Giudici
· 45,991 Views
article thumbnail
The Four Pillars of ASP.NET
Not that long ago, there was just ASP.NET. But ASP.NET has expanded to include different approaches to development. Recently, I was chatting with Microsoft’s Scott Hunter and Steve Walther over drinks at DevConnections Orlando and Steve mentioned “the four pillars of ASP.NET.” The four pillars are the four ways you can build web sites with ASP.NET, both today and in the future. The four pillars are: 1. ASP.NET Web Forms. Until recently, this was the only pillar of ASP.NET. Everything was done using the familiar rich server-side controls that many have grown to love (and some have learned to despise which is the seed for the other three pillars). So what’s wrong with Web Forms? Well, many developers believe that ASP.NET Web Forms are too much of a black box with a healthy-dose of black magic. There’s a price you pay for the Web Form event model and lifecycle and that price is control over the exchange of data between server and browser. Some say the Web Form model with its incessant ViewState is a pig. The Web Form model also makes it difficult to create testable applications and practice test-driven development (TDD). On the other hand, ASP.NET AJAX and ASP.NET MVC (pillars 2 and 3, respectively) come with a steep learning curve, and for many developers will take longer to develop the equivalent application. Pillar 4 (Dynamic Data), on the other hand, has limited applicability, IMO. My opinion is that with the possible exception of Dynamic Data for the creation of simpler intranet applications, nothing in my mind beats ASP.NET Web Forms (especially when paired with the ASP.NET AJAX UpdatePanel control) for creating good, solid, and responsive applications that, while not the leanest and meanest of applications nor very testable, are easy to grok and master for the novice through advanced developer. Web forms are also the best match for the developer looking to make the move to ASP.NET from Microsoft desktop (Win Forms or WPF) development. And with each new version, Microsoft is making it easier to tame the pig (ViewState) and reduce its size: ASP.NET 2.0 introduced ControlState and ASP.NET 4.0 changes the inheritance model of ViewState so it will be easier to turn off ViewState by default and only turn it on when needed. 2. ASP.NET AJAX. This pillar came to life with the ASP.NET AJAX Extensions for ASP.NET 2.0 / Visual Studio 2005. ASP.NET AJAX is now integrated into ASP.NET and Visual Studio 2008 and consists of both a set of server-side controls as well as the AJAX client-side libraries. In regards to its existence as a “pillar,” I would argue that Microsoft is really only talking about the client-side of ASP.NET AJAX. The reason I say this is that the Upgrade Panel and other server-side AJAX controls merely extend the Web Form pillar, giving Web Form controls the ability to do asynchronous postbacks. There are many in the hard-core ASP.NET AJAX community that believe that a true AJAX application needs to be built from the ground up without the use of Web Forms and the server-side controls. Using this approach, ASP.NET merely becomes a way to emit HTML with embedded JavaScript (and references to the Microsoft ASP.NET AJAX and JQuery libraries) that calls back to ASP.NET (or WCF) web services. When the HTML and JavaScript hit the browser, that’s when the action begins. The promise of this approach is a much snappier user interface and a much more scalable web site. On the downside, this requires programming in a loosely-typed language with a weird inheritance model, spotty support for IntelliSense, and, while improved, lousy debugger support. Another downside, the lack of smart client-side controls is likely to be remedied in the ASP.NET 4.0 timeframe. Microsoft is busy improving the client-side story, complete with client-side controls, for ASP.NET 4.0 (if you are curious, check out http://asp.net/ajax and click on the “ASP.NET AJAX Preview on CodePlex” link for a peek at what’s coming). Regardless, I believe this pillar will always be for a subset of ASP.NET developers who don’t shun the client-side. 3. ASP.NET MVC. This pillar is the newest to emerge from Microsoft. In fact, as of this writing, it’s only a couple of weeks old, having been released at Mix09. Some ASP.NET curmudgeons would call this a throwback to the days of ASP “classic” spaghetti code, but for many others--especially the alt.net crowd and transplants from Ruby and Java--this represents the cat’s pajamas on the Microsoft web stack. (Of course, it’s amazing how quickly developers find problems in the latest programmer’s paradise--usually before its release--and I’m sure the MVC aficionados are already looking to the next release.) The basic idea behind ASP.NET MVC is to separate out the three concerns of the MVC pattern: the model, view, and controller. The model represents the data model, the view is the user interface that presents the data and interacts with the user, and the controller is the command center that takes inputs from the view, pushes and pulls data into/from the model, and decides what to do next. By separating out these concerns (as purely as possible), you improve the ability to create unit tests for your applications and, at least on some level, improve application maintainability. If you are into test driven development, then this is the pillar to hook your horse to. 4. Dynamic Data. IMO, Dynamic Data is a misnomer. From its name, one would tend to think this is yet another data access technology from Microsoft. It is not. I would have preferred Microsoft to use the name Dynamic Application or Dynamic Application Builder. MSDN Help says, “ASP.NET Dynamic Data is a framework that lets you create data-driven ASP.NET Web applications easily.” You start with Dynamic Data by creating a database and then using either LINQ to SQL or the Entity Framework to create a model over your data. Next, create a new project or web site in Visual Studio 2008 (with SP1) using one of the Dynamic Data Web Application templates, make a fairly simple change to the web site’s Global.asax, and Visual Studio builds a dynamic ASP.NET application over your data model. The resulting site support the creation, retrieval, updating, and deletion (commonly referred to as the CRUD operations) of rows in the underlying database. Dynamic Data uses what is termed dynamic scaffolding to construct your application. This means if you change your data model, the application will be instantly updated: there’s no code that needs to be re-generated. Dynamic Data is customizable. Thus, if you don’t like how Dynamic Data presents a datatype or a particular field, or want to change how it performs validation of a field, you can change the templates behind these. You can also change the master page used as well as a number of other details. Kudos to Microsoft for Dynamic Data--even though I hate the name. Just realize that this pillar, unlike the other three, is only applicable to a subset of ASP.NET applications that fit in well with the Dynamic Data approach to applications: applications, which are primarily data-centric, intranet-based applications. That said I could see many places where I might use Dynamic Data, though I am still trying to work through the security implications of opening up the database for pretty much unrestricted reading and writing of database tables. (For those who would like to see an MVC version of Dynamic Data: I’d expect to see such a beast come down the pike at some point from Microsoft.) Conclusion So what does this mean to the developer? I have both good and bad news. The good news is that you now have a choice in how you develop your ASP.NET applications. If you love the responsiveness and coolness of AJAX or you need to scale your applications big-time, then you’ll love ASP.NET AJAX. If, OTOH, you are into unit tests or TDD, you will love ASP.NET MVC. Finally, if you were looking for an easier way to build you basic CRUD web application, you’ll want to take a look at Dynamic Data. Don’t need any of the above? There’s no need to despair--ASP.NET Web Forms are here for the long haul! The bad news is that you now have a choice in how you develop your ASP.NET applications. (Wait a second, wasn’t that also the good news?)This means you have more things to learn. It also means that in trying to support all four pillars, Microsoft may be taking some of its focus off Web Forms. After all, there’s only so many PMs and devs at Microsoft on the ASP.NET team. Furthermore, this means that if you are a manager like me worried about maintainability of applications and hiring developers, your job just got more difficult because one person’s idea of ASP.NET development is not necessarily someone else’s. Still, I think the good news here, outweighs the bad. Microsoft used to present ASP.NET Web Forms vs. MVC as a choice between a car and a motorcycle. Both will get you to your job , but some (the majority of the population, I might add) prefer driving a car, while a sizable minority love their motorcycles which give you better gas mileage and independence, but don’t protect you in the rain. To stretch this analogy to its breaking point, let me suggest that ASP.NET AJAX is like riding a bicycle to work (lean and mean, best gas mileage, but it requires you to exercise for your commute and exposes you to the elements like the motorcycle) while Dynamic Data is like taking the bus to work (let metro do the driving for you.) What about Silverlight? Silverlight is really just the next generation of a one-click desktop application, that is hosted in the browser and runs on a multi-platform .NET virtual machine. Not to take anything away from Silverlight, but it’s not ASP.NET. Does this mean that ASP.NET Web Forms is going away? Although some people “in the know” have stated in the past couple of years that either ASP.NET AJAX or ASP.NET MVC was the future of ASP.NET, this is not the official position of Microsoft. Think about it, since 98%--yes, this is a total educated guess--of ASP.NET development is still done using ASP.NET Web Forms, and this percentage is unlikely to change significantly over the next several years, Microsoft would be stupid to kill off Web Forms. It doesn’t make any economic sense, and since Microsoft is a for-profit entity, I think Web Forms will be a major thrust of ASP.NET for many years to come. In my opinion, Microsoft has added the three new pillars for the following reasons: · Microsoft is always trying to follow innovation and buzz in the industry. Three years ago, that buzz was in AJAX. Today, MVC, separation of concerns, and TDD is all the rage so Microsoft has countered with ASP.NET MVC. · Microsoft is always trying to broaden the appeal of ASP.NET. Microsoft has been trying to woo the open source community for years (after initially discounting it). And in order to do this, it needs to embrace many of the ideals of this community, which tends to live on the bleeding edge and is into AJAX, testability, and TDD, amongst other things. · Microsoft truly wants to improve the productivity of its customers. After all, if you improve the ability of your customers, in our case corporate and independent developers, to get their jobs done, you’ve gone a long way to attracting and retaining customers. In Microsoft’s eyes (and many of its customers), this is a win, win situation. I, for one, would like to thank Microsoft for the four pillars of ASP.NET. In producing the four pillars, Microsoft has given ASP.NET developers the choices they both want and need.
April 30, 2009
by Paul Litwin
· 10,626 Views
article thumbnail
Making Distinctions Between Different Kinds of JSF Managed-Beans
JSF has a simple Inversion-of-Control (IoC) container called the JSF Managed Bean Facility (MBF). Although it has a verbose XML syntax, and is not as robust as the Spring BeanFactory, PicoContainer, or the JBoss Microcontainer, the MBF does have the basics of an IoC container, and offers features like dependency injection. When a POJO is managed by the JSF MBF, it is typically referred to as a managed-bean. But if you're going to create a maintainable JSF webapp/portlet, it is necessary to distinguish between different kinds of managed-beans. This practice will also preserve the clean separation of concerns that JSF provides by implementing the Model-View-Controller (MVC) design pattern: Managed-Bean Type Nickname Typical Scope Model Managed-Bean model-bean session Description: This type of managed-bean participates in the "Model" concern of the MVC design pattern. When you see the word "model" -- think DATA. A JSF model-bean should be a POJO that follows the JavaBean design pattern with getters/setters encapsulating properties. The most common use case for a model bean is to be a database entity, or to simply represent a set of rows from the result set of a database query. Backing Managed-Bean backing-bean request Description: This type of managed-bean participates in the "View" concern of the MVC design pattern. The purpose of a backing-bean is to support UI logic, and has a 1::1 relationship with a JSF view, or a JSF form in a Facelet composition. Although it typically has JavaBean-style properties with associated getters/setters, these are properties of the View -- not of the underlying application data model. JSF backing-beans may also have JSF actionListener and valueChangeListener methods. Controller Managed-Bean controller-bean request Description: This type of managed-bean participates in the "Controller" concern of the MVC design pattern. The purpose of a controller bean is to execute some kind of business logic and return a navigation outcome to the JSF navigation-handler. JSF controller-beans typically have JSF action methods (and not actionListener methods). Support Managed-Bean support-bean session / application Description: This type of bean "supports" one or more views in the "View" concern of the MVC design pattern. The typical use case is supplying an ArrayList to JSF h:selectOneMenu drop-down lists that appear in more than one JSF view. If the data in the dropdown lists is particular to the user, then the bean would be kept in session scope. However, if the data applies to all users (such as a dropdown lists of provinces), then the bean would be kept in application scope, so that it can be cached for all users. Utility Managed-Bean utility-bean application Description: This type of bean provides some type of "utility" function to one or more JSF views. A good example of this might be a FileUpload bean that can be reused in multiple web applications. Now... One of the main benefits in making fine distinctions like this is loose coupling. What's that you ask? Well let's first take a look at an example of tight coupling, where MVC concerns can be smashed/confused into a single managed-bean: public class ModelAndBackingAndControllerBean { private String fullName; // model-bean property private boolean privacyRendered; // backing-bean property // model-bean getter public String getFullName() { return fullName; } // model-bean setter public void setFullName(String fullName) { this.fullName = fullName; } // backing-bean getter public boolean isPrivacyRendered() { return privacyRendered; } // backing-bean setter public void setPrivacyRendered(boolean privacyRendered) { this.privacyRendered = privacyRendered; } // backing-bean actionListener for UI support logic public void togglePrivacySection(ActionEvent actionEvent) { privacyRendered = !privacyRendered; } // controller-bean business logic public String submit() { System.out.println("fullName=" + fullName); return "success"; } } The problem here is that the bean would have to be kept in session scope because of the model-bean property. Additionally, what if we wanted to do some unit testing with mock model data? Can't do it. So in order to fix these problems, and to promote loose coupling, we would have three separate Java classes: public class ModelBean { private String fullName; public void setFullName(String fullName) { this.fullName = fullName; } public String getFullName() { return fullName; } } public class BackingBean { private boolean privacyRendered; public void setPrivacyRendered(boolean privacyRendered) { this.privacyRendered = privacyRendered; } public boolean isPrivacyRendered() { return privacyRendered; } public void togglePrivacySection(ActionEvent actionEvent) { privacyRendered = !privacyRendered; } } public class ControllerBean { private ModelBean modelBean; public ModelBean getModelBean() { return modelBean; } public void setModelBean(ModelBean modelBean) { // Dependency injected from the JSF managed-bean facility this.modelBean = modelBean; } public String submit() { System.out.println("fullName=" + getModelBean().getFullName()); return "success"; } } Now that the beans are found in different classes, they can all be kept in their appropriate scopes. The model-bean can be kept in session scope, and the backing-bean and controller-bean can be kept in request scope, thus saving memory resources on the server. Finally, we can use the dependency injection features of the JSF MBF in order to inject the model-bean into the controller-bean. This can be seen in the following WEB-INF/faces-config.xml example, where the #{modelBean} Expression Language (EL) binding is used: modelBean myproject.ModelBean session backingBean myproject.BackingBean request controllerBean myproject.ControllerBean request modelBean #{modelBean} From http://blog.icefaces.org/
April 24, 2009
by Neil Griffin
· 64,070 Views · 2 Likes
article thumbnail
Building a Simple RSS Client in Pivot
A few months ago, this article by Andrew Trice inspired me to write a demo application to see how well Pivot would handle very large tabular data sets of up to one million rows (the results are here). Mr. Trice has again inspired me, this time to see how easy it might be to to write a Pivot application that consumes an RSS feed and presents the data in a list view using a custom item renderer. This article describes the results. The Demo Application The following image shows a screen shot of the demo application, which retrieves RSS feed data from Javalobby. A live example is available here (it requires Java 6 Update 10 or later; see notes at bottom of page). The application contains a single ListView component in a ScrollPane that is used to present the news data. A custom list item renderer is used to display the item's title, categories, and submitter. The WTKX source for the demo's UI is as follows: It's pretty straightforward: a root Border component contains a CardPane containing two sub-panes. The first is a status label that is used to provide feedback to the user while the feed is being loaded. The second is a ScrollPane containing the actual list view used to present the feed data. The Java source is a bit more involved. It is broken into two files: one contains the main application class, and the other contains an adapter class that is used to wrap an XML node list such that it can be used as the data model for the list view. The application class contains several inner classes that are used to facilitate loading and presenting the data, as well as opening the articles in an external browser window when the user double-clicks on the list. The Main Application Class The application's constructor is shown below: public RSSFeedDemo() { // Create an XPath instance xpath = XPathFactory.newInstance().newXPath(); // Set the namespace resolver xpath.setNamespaceContext(new NamespaceContext() { public String getNamespaceURI(String prefix) { String namespaceURI; if (prefix.equals("dz")) { namespaceURI = "http://www.developerzone.com/modules/dz/1.0"; } else { namespaceURI = XMLConstants.NULL_NS_URI; } return namespaceURI; } public String getPrefix(String uri) { throw new UnsupportedOperationException(); } public Iterator getPrefixes(String uri) { throw new UnsupportedOperationException(); } }); } Using the newInstance() factory method, it obtains an instance of javax.xml.xpath.XPath that is later used to retrieve element values from the returned data. A namespace resolver is then set on the XPath, allowing it to map the "dz" prefix to the "http://www.developerzone.com/modules/dz/1.0" namespace URI. The startup() method is defined as follows: public void startup(Display display, Dictionary properties) throws Exception { WTKXSerializer wtkxSerializer = new WTKXSerializer(); window = new Window((Component)wtkxSerializer.readObject(getClass().getResource("rss_feed_demo.wtkx"))); feedListView = (ListView)wtkxSerializer.getObjectByName("feedListView"); feedListView.setItemRenderer(new RSSItemRenderer()); feedListView.getComponentMouseButtonListeners().add(new FeedViewMouseButtonHandler()); final CardPane cardPane = (CardPane)wtkxSerializer.getObjectByName("cardPane"); final Label statusLabel = (Label)wtkxSerializer.getObjectByName("statusLabel"); LoadFeedTask loadFeedTask = new LoadFeedTask(); loadFeedTask.execute(new TaskListener() { public void taskExecuted(Task task) { feedListView.setListData(new NodeListAdapter(task.getResult())); cardPane.setSelectedIndex(1); } public void executeFailed(Task task) { statusLabel.setText(task.getFault().toString()); } }); window.setMaximized(true); window.open(display); } It loads the UI from the WTKX file, sets it as the content of a decorationless window, and obtains references to some of the components defined in the file. It assigns an instance of RSSItemRenderer as the item renderer for the list view and attaches an instance of FeedViewMouseButtonHandler as a mouse button listener on the list view (these classes are discussed in more detail below). It then creates an instance of LoadFeedTask, executes the task, and opens the window. LoadFeedTask LoadFeedTask is a private inner class that is used to load the feed data on a background thread so the UI doesn't block while it is being loaded. It is defined as follows: private class LoadFeedTask extends IOTask { public NodeList execute() throws TaskExecutionException { NodeList itemNodeList = null; DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder documentBuilder; try { documentBuilder = documentBuilderFactory.newDocumentBuilder(); } catch(ParserConfigurationException exception) { throw new TaskExecutionException(exception); } Document document; try { document = documentBuilder.parse(FEED_URI); } catch(IOException exception) { throw new TaskExecutionException(exception); } catch(SAXException exception) { throw new TaskExecutionException(exception); } try { itemNodeList = (NodeList)xpath.evaluate("/rss/channel/item", document, XPathConstants.NODESET); } catch(XPathExpressionException exception) { // No-op } return itemNodeList; } } The execute() method loads an XML document from the feed URI and then uses the XPath object to obtain a node list containing the item elements, which it returns. Upon successful execution, the taskExecuted() method of the task listener is called. This method wraps the returned node list in an instance of NodeListAdapter, which is used to adapt the contents of the NodeList for consumption by the ListView (the source code for this class is available here). If the load fails, the resulting execption is displayed in the status label. RSSItemRenderer The RSSItemRenderer class prepares the feed data for presentation in the list view. It implements the ListView.ItemRenderer interface and extends a vertical FlowPane, which it uses to arrange Label instances containing each article's title, categories, and submitter (note that, while this implementation creates the flow pane's layout programmatically, it could also have been defined in WTKX): private class RSSItemRenderer extends FlowPane implements ListView.ItemRenderer { private Label titleLabel = new Label(); private Label categoriesHeadingLabel = new Label("subject:"); private Label categoriesLabel = new Label(); private Label submitterHeadingLabel = new Label("submitter:"); private Label submitterLabel = new Label(); public RSSItemRenderer() { super(Orientation.VERTICAL); getStyles().put("padding", new Insets(2, 2, 8, 2)); add(titleLabel); FlowPane categoriesFlowPane = new FlowPane(); add(categoriesFlowPane); categoriesFlowPane.add(categoriesHeadingLabel); categoriesFlowPane.add(categoriesLabel); FlowPane submitterFlowPane = new FlowPane(); add(submitterFlowPane); submitterFlowPane.add(submitterHeadingLabel); submitterFlowPane.add(submitterLabel); } ... The render method obtains the font and color styles from the component and applies them to its internal labels. It then sets the contents of the labels by extracting the element content from the current node. ... public void render(Object item, ListView listView, boolean selected, boolean checked, boolean highlighted, boolean disabled) { // Render styles Font labelFont = (Font)listView.getStyles().get("font"); Font largeFont = labelFont.deriveFont(Font.BOLD, 14); titleLabel.getStyles().put("font", largeFont); categoriesLabel.getStyles().put("font", labelFont); submitterLabel.getStyles().put("font", labelFont); Color color = null; if (listView.isEnabled() && !disabled) { if (selected) { if (listView.isFocused()) { color = (Color)listView.getStyles().get("selectionColor"); } else { color = (Color)listView.getStyles().get("inactiveSelectionColor"); } } else { color = (Color)listView.getStyles().get("color"); } } else { color = (Color)listView.getStyles().get("disabledColor"); } if (color instanceof Color) { titleLabel.getStyles().put("color", color); categoriesHeadingLabel.getStyles().put("color", color); categoriesLabel.getStyles().put("color", color); submitterHeadingLabel.getStyles().put("color", color); submitterLabel.getStyles().put("color", color); } // Render data if (item != null) { Element itemElement = (Element)item; try { String title = (String)xpath.evaluate("title", itemElement, XPathConstants.STRING); titleLabel.setText(title); String categories = ""; NodeList categoryNodeList = (NodeList)xpath.evaluate("category", itemElement, XPathConstants.NODESET); for (int j = 0; j < categoryNodeList.getLength(); j++) { Element categoryElement = (Element)categoryNodeList.item(j); String category = categoryElement.getTextContent(); if (j > 0) { categories += ", "; } categories += category; } categoriesLabel.setText(categories); String submitter = (String)xpath.evaluate("dz:submitter/dz:username", itemElement, XPathConstants.STRING); submitterLabel.setText(submitter); } catch(XPathExpressionException exception) { System.err.println(exception); } } } } FeedViewMouseButtonHandler The FeedViewMouseButtonHandler class handles double-clicks on the list view. Clicking the list view once stores the index that was clicked (in case the user moves the mouse before a double-click occurs), and the selected item is opened on the double-click: private class FeedViewMouseButtonHandler extends ComponentMouseButtonListener.Adapter { private int index = -1; @Override public boolean mouseClick(Component component, Mouse.Button button, int x, int y, int count) { if (count == 1) { index = feedListView.getItemAt(y); } else if (count == 2 && feedListView.getItemAt(y) == index) { Element itemElement = (Element)feedListView.getListData().get(index); try { String link = (String)xpath.evaluate("link", itemElement, XPathConstants.STRING); BrowserApplicationContext.open(new URL(link)); } catch(XPathExpressionException exception) { System.err.print(exception); } catch(MalformedURLException exception) { System.err.print(exception); } } return false; } }; Summary So, building an RSS reader in Pivot was fairly straightforward. The XPath APIs included in the Java platform are very efficient for retrieving and parsing the feed data, and Pivot makes it easy to wrap the returned XML data in a list model and customize it's presentation in the list view. However, one important lesson learned is that that Java's XML factory methods don't play nicely with applets. They rely on the JAR service provider architecture and will repeatedly look for service descriptor files on the applet's classpath, resulting in many unnecessary requests to the web server. The only way to prevent this is to set the codebase_lookup applet parameter to false: This works, but it is an ugly workaround - there are certainly valid use cases for using both codebase lookup and XML parsing in an applet; for example, an applet that parses XML that is dynamically generated from a servlet on the applet's classpath. Hopefully Sun (or Oracle) will address this issue in a future JVM update. Also note that this demo takes advantage of Java 6 Update 10's new support for crossdomain.xml files. This handy feature allows an unsigned applet to make a network connection to a server outside of its origin, provided it was loaded from an approved URL. See this article for more information. The full source code for the demo is available here. For more information on Apache Pivot, visit http://incubator.apache.org/pivot.
April 23, 2009
by Greg Brown
· 9,760 Views
article thumbnail
GraphML Viewer for the Web
GraphMLViewer is a freely available, Flash®-based, interactive viewer which displays diagrams, networks, and other graph-like structures in HTML web pages. It is optimized for diagrams created with the also freely available yEd graph editor and the yFiles Java diagramming library. Features of the GraphMLViewer include: Viewer application for diagrams in GraphML format: GraphMLViewer is created to display diagrams which are saved in GraphML format. GraphML is the XML-standard for saving graph-like diagrams. The viewer is optimized for diagrams which were created with the freely available yEd graph editor. Users can freely move and resize the displayed diagram A small, interactive overview of the diagram can be displayed. The current diagram can be printed. Descriptions which are added to graph elements in yEd can be displayed as tooltips. Users can navigate to URLs that can be added to graph elements in yEd via mouse click. Most of these features can be configured via parameters in the embedding HTML. This enables web authors to adapt the viewer to their requirements. The freely available yEd graph editor offers the option to export all needed files with a simple mouse click (export as "HTML Flash Viewer;" since version 3.2). GraphMLViewer makes use of the yFiles FLEX Actionscript library. This is a Flex® library that allows to integrate the viewing, editing, and animation of a wide range of diagrams, networks, and other graph-like structures into rich internet applications based on Adobe® Flex® or AIR™. For more information, please see the GraphMLViewer home page which provides more details on the features of the GraphMLViewer and explains howthe viewer can be embedded into web pages. About yWorks yWorks specializes in professional software solutions for the visualization of diagrams and graphs. Our yFiles product family offers high-quality diagramming for Java and .NET applications as well as for browser applications based on Adobe® Flex™ or AJAX technology. The extensive yFiles Java class library and the .NET class libraries yFiles.NET and yFiles WPF deliver state-of-the-art component technology which can easily be integrated into Java applications, servlets, and applets, and Windows Forms, ASP.NET, and Windows Presentation Foundation (WPF) applications, respectively. Our web products yFiles FLEX and yFiles AJAX are a perfect fit for web-based diagramming applications that use state-of-the art web technologies.
April 7, 2009
by Sebastian Mueller
· 29,285 Views
article thumbnail
Wicket Tutorial Series: Setting Up the Project
Each day this week will feature a new article with an in-depth look at the creation process behind setting up a Java project and implementing the frontend with Apache Wicket. Wicket is a Java web application framework which allows “Designers” (people good with Dreamweaver) and “Developers” (people good with Java and Databases) to collaborate on a project with minimal chances of stepping on each other’s toes or wearing each other’s hats. The beauty of Wicket is that it uses plain xhtml pages as it’s templating markup. This means that html pages can be loaded into Dreamweaver (or whatever tool the Designer is comfortable with) and they will look very close to the same as they would when rendered on the deployment web server. Workflow The basic workflow involved in creating and maintaining html rendered by Wicket is as follows: The Designer creates the html for the website and fleshes it out with “mock” sections. For instance in the application we intend to create during our Five Days of Wicket will be a pastebin application called “Mystic Paste”. In our application we’ll have an “Add Code to Mystic Paste” page, mock data might include some user created content in the textarea of the page. All css/images, etc… are setup such that if they were to be put on a webserver, everything would work. The Developer needs to flesh out the dynamic areas of the webpage, that is, he needs to instruct Wicket where it will need to show information from the server. The developer does this by decorating the designer’s html page with special Wicket tags and attributes. Because these tags and attributes are just considered part of another namespace separate from xhtml’s, editors like Dreamweaver and browsers will simply ignore them - It is important to note: The developer will still keep the “mocked” sections of the page intact, this is so the page renders and looks fleshed out on its own. The mocked sections will be replaced by real data when rendered by Wicket. The Developer hands the file back to the Designer. The Designer is free to make further edits, so long as he/she does not remove or manipulate the Wicket tags and attributes present in the file. If the Designer does need to remove any Wicket tags or attributes, they need to consult the Developer as such an action will “break” the webpage when Wicket renders it. Example Wicket Page Here is an example of a Wicket page. This example was taken from Manning Publishing’s book “Wicket in Action”: ... Gouda Gouda is a Dutch... $1.99 add to cart Emmental Emmental is a Swiss che... $2.99 add to cart ... This looks almost 100% like a normal webpage would look, the only difference is the addition of the “wicket:XXX” attributes and tags sprinkled through the document. The parts of the document using the special Wicket namespace modifiers will be replaced/removed in the final markup when Wicket renders the page to the user’s browser. Notice the “” element? This is where your designer can put a “mocked” version of what that area of the page should look like. You as a developer can take that mocked html and divide it out into a template that is dynamically driven from the backend. Here is how the final page looks if you were to simply load the page into a web browser (or Dreamweaver) from your hard drive: Preparing for Setup Deviating a bit from the Standard Wicket Convention One of the first things a developer notices when starting out with Wicket is the convention where Wicket likes having its html template files live at the same level and in the same packages as it’s Java source files. Sure you can jump through hoops to get Wicket to load the html template files from elsewhere but a nice compromise is to simply keep your html template files within the same package directory structure but in a source folder separate from the Java classes. Why? Well quite simply to keep your designers (Dreamweaver folks!) from having to grab Java source files along with the html files they are working on. It will just confuse them and clutter their directories. You can of course stick with the typical “Java source files along side html” convention if you wish, but I find it much cleaner to separate them during design time, and have Maven combine them only at build time into the target war (which it will gladly do automagically). Project Folder Structure . |-- pom.xml |-- src | `-- main | |-- filters | |-- java | | `-- com | | `-- mysticcoders | | `-- mysticpaste | | |-- model | | |-- persistence | | | |-- exception | | | |-- hibernate | | |-- services | | `-- web | | |-- ajax | | |-- pages | | |-- panels | | `-- servlet | |-- resources | | |-- com | | | `-- mysticcoders | | | `-- mysticpaste | | | |-- spring | | | `-- web | | | |-- ajax | | | |-- pages | | | `-- panels | | `-- log4j.properties | |-- sql | `-- webapp | |-- WEB-INF | |-- images | |-- js | `-- css src/main: maven builds source and resources from this directory to the main deployable target (i.e. our war file) filters: we keep a set of “filters” files that maven can use to interpolate variables at build time. What does this mean? It means that inside your configuration files, the files you use to setup database connections or file paths, you can insert variable place holders like ${db.host}. When maven does a build, it looks up the correct filter file to use and looks for the key=value part corresponding to “db.host” and inserts it into the configuration file for you. This ensures that you are able to configure your application per environment you deploy to (i.e. DEV, QA, PROD, etc…) by having different filter files with the same keys but different values. For more information see Maven’s documentation on filtering resource. java/*: this folder will contain all of the application’s source code. Everything from the database access code, wicket code and services code for the mysticpaste application (see below). model: all “domain” classes, that is, classes that represent the objects in the application. For mysticpaste you’ll see classes like “PasteItem” which represents an item pasted to the mysticpaste. persistence: at this level of the persistence package a list of interfaces will be kept. The interfaces comprise the basic access layer the services layer will use to save, retrieve and update items to/from the paste bin. exception: the peristence layer needs to tell the services layer when things have gone wrong. It does this via delcaring and throwing exceptions. hibernate: such is our case, our persistence interfaces will be implemented via the ORM known as Hibernate. This package will store all of the custom hibernate implementations and hibernate specific classes services: The services layer will be stored here. Both the generic interfaces and their implementation classes. The persistence layer will be injected via spring. web: this folder is where our Wicket classes will reside and it’s split into several category packages which are as follows: ajax: mysticpaste uses Ajax to render portions of its UI. The wicket classes which render the xml/html to be injected dynamically into the page are stored here. pages: standard Wicket page classes which are used throughout the application are stored here panels: reusable panel classes are stored here. Panels may be included within Wicket pages for sake of templating servlet: any run of the mill servlet code we need is stored here. A good example might be an ImageUploadServlet resources/*: the resources folder will hold our non-java based files. Noteably html files and spring confguration files spring: Holds any spring configuration files needed to wire the services and persistence layer web: this folder and all subfolders mirror the packages under src/main/java/…/web and hold the .html files that the Wicket page/panel classes use as their templates. As described above, a “standard” wicket application simply stores the .html files along side their Wicket classes under src/main/java/…/web, however we want to keep these files separate from the Java source so as to keep the directory our designers checkout from version control contianing only the files they need to work on. sql: any sql scripts we need to keep handy for building the mysticpaste database. webapp: this folder will keep the files which live at the base directory of our war file WEB-INF: where you keep your web.xml file images: any image resource, .gif/.png/.jpg files your webapp will reference js: javascript files your webapp will reference css: style sheets your webapp uses src/test/*: All files which reside under this folder are test classes and resources needed to support the tests. Maven will build everything under src/main/java and add it to the class path of the JUnit or TestNG classes you create. java: JUnit or TestNG test classes which will be run during a build resources: resource files which are needed to support the tests Getting Started Since we are using Maven as our build tool we can take advantage of the fact that the fine folks at the Wicket project have created a specialized “archetype“ which creates a skeleton web application complete with a folder structure which mimics roughly what we have outlined above and Maven pom.xml file used to build a war. The Wicket contributors have even gone one step further and have created a little web page which will, based off a few drop down options, generate the maven command you need to execute in order to create the boiler plate Wicket project. You can find this web page over on the Apache Wicket site under the “Quick Start” link. Copying the above Maven command creates a Skeleton Wicket Project To be precise, the command I used was: mvn archetype:create -DarchetypeGroupId=org.apache.wicket -DarchetypeArtifactId=wicket-archetype-quickstart -DarchetypeVersion=1.3.5 -DgroupId=com.mysticcoders -DartifactId=mysticpaste And I ended up with the following folder structure: . `-- mysticpaste |-- pom.xml `-- src |-- main | |-- java | | `-- com | | `-- mysticcoders | | |-- HomePage.html | | |-- HomePage.java | | `-- WicketApplication.java | |-- resources | | `-- log4j.properties | `-- webapp | `-- WEB-INF | `-- web.xml `-- test `-- java `-- com `-- mysticcoders |-- Start.java `-- TestHomePage.java Now obviously we’ll have to rearrange a few things, for instance I want my base package to be com.mysticcoders.mysticpaste, but that’s easy enough to do once we are in an IDE. For now, let’s test this example webapp out and see if it works. To do that switch into the mysticpaste directory (the directory that has pom.xml in it) and type the following: mvn jetty:run This will start up a Jetty webapp container running on port 8080 (if you have something running there already, use the -Djetty.port= option). Startup a webbrowser and navigate to http://localhost:8080/mysticpaste/ You should see: Your IDE Sooner or later you’re going to want to crack open your IDE and start hacking away. Maven makes this extremely easy by allowing you to create IDE specific project files based off of the Maven pom.xml file. Eclipse mvn eclipse:eclipse For eclipse you’ll also have to set the M2_REPO classpath variable for the workspace your project resides under. Do this by entering the following command: mvn -Declipse.workspace= eclipse:add-maven-repo IntelliJ IDEA mvn idea:idea -OR- in IDEA 7+ simply open the pom.xml file Netbeans Netbeans supports maven out of the box, just “Open Project” and choose the mysticpaste directory that contains the pom.xml file When generating the project files through Maven, the project is setup such that classpath entries point to your local Maven repository (i.e. ~/.m2/repository, or C:Documents and Settingsyourusername.M2repository on Windows). It also sets up src/main/java, src/main/resources as “source folders”. You may add other folders to the source folder list as per your IDE if needed, the only thing you have to remember is if you ever use mvn eclipse:clean followed by mvn eclipse:eclipse again, those other source folders will have to be readded through your IDE. Instead, you should add the source/resource folders directly to your pom.xml, this way they will be maintained. Spring The Mystic Paste application will use Spring, and really you should too. Unless you have been hiding under a rock or work in a corporate environment so lame as to which technologies newer than 2002 are forbidden you should learn to accept Spring as a defacto standard. Dependency injection for the win! We add the following to our pom.xml: org.apache.wicket wicket-spring-annot org.springframework spring org.springframework spring-test org.springframework spring-tx wicket-spring-annot: allows us to wire our Wicket application via handy dependency injection annotations (i.e. @SpringBean, see Wicket documentation for more detail) spring: is just the core spring libraries spring-test: is a set of Spring integration classes for Unit testing spring-tx: is the Spring Transaction Management api for declarative transactions web.xml additions for Spring In order for Spring to manage our Wicket application we need to setup the Wicket filter with a Spring-aware application factory. This allows us to wire our Wicket Application class in our applicationContext.xml file, which is really handy if you have a services and configuration settings you want to inject into the Wicket Application object so the rest of your application can access them. To do this, we change the original Wicket filter like so: wicket.mysticpaste org.apache.wicket.protocol.http.WicketFilter applicationFactoryClassName org.apache.wicket.spring.SpringWebApplicationFactory As well, we want our Spring context to be available to our webapp if ever there is a need for one of our pages to access the Spring managed beans directly: contextConfigLocation classpath:com/mysticcoders/mysticpaste/spring/applicationContext.xml org.springframework.web.context.ContextLoaderListener Hibernate Hibernate is our ORM of choice, it will allow us to persist and retrieve our model objects to and from the underlying database, whatever that database may be. We add the following to our pom.xml: org.hibernate hibernate-annotations c3p0 c3p0 commons-dbcp commons-dbcp javax.transaction jta 1.0.1B hibernate-annotations: used so we can annotate our model classes with mapping information, instead of having to create a separate mysticpaste.hbm.xml file. c3p0: provides a connection pooling library Hibernate can use commons-dbcp: another connection pooling library, we’ll add it as well and decide whether to use it or c3p0 later jta: this is the Java Transaction API which is needed by Hibernate (Hibernate provides an implementation of the API) web.xml additions for Hibernate To have a Hibernate Session open and ready for our webapplication during a Request Cycle we need to setup a Hibernate filter like so (otherwise, good luck getting lazy loading working!): open.hibernate.session.in.view org.springframework.orm.hibernate3.support.OpenSessionInViewFilter open.hibernate.session.in.view /* As the comment states above, make sure this filter-mapping exists *before* your wicket.mysticpaste filter or else it just plain won’t work. Database For the Mystic Paste we decided to use the freely available PostgreSQL. Adding support for PostgreSQL is very easy, unlike with some of the commercial DBMSes where you have to download and install their JDBC driver into your repository. To add support for Postgres, we simply add the following to our pom.xml: postgresql postgresql Servlets Regardless of which webapplication framework you choose there are just some times when a plain jane Servlet comes in really handy. If you have a need for Servlets and the Servlet must have access to the Wicket session add the following to your web.xml: wicket.session org.apache.wicket.protocol.http.servlet.WicketSessionFilter filterName wicket.mysticpaste And then, after your other filter-mappings add the following (assuming you mount your servlet-mappings under /servlet/): wicket.session /servlet/* Maven Filters and Profiles In order to build our Mystic Paste project for various environments (DEV/QA/PROD) we need to implement both Maven profiles and filters. Filters Filters allow you to place variables inside your configuration files and have those variables filled in durring build time. This is very handy for setting environment specific things such as database connection information. Enabling filters is quite easy, we open up the pom.xml file and find the section for and set the value for the element to true as follows: true src/main/resources . . . But for filtering to work, we need to specify a filters file. It’s not enough to specify only one filter file because we need to specify different filters per environment and we’ll do that by using Maven Profiles. Profiles To setup a profile, create a new set of elements following the section in your pom.xml file. Like so: DEV DEV DEV QA QA PROD PROD and just above your tag underneith your tag you would add the following elements: mysticpaste src/main/filters/filters-${env}.properties true src/main/resources src/main/filters will contain the following files. |-- pom.xml |-- src | `-- main | |-- filters | | `-- filters-DEV.properties | | `-- filters-QA.properties | | `-- filters-PROD.properties filters-DEV.properties jdbc.url=jdbc:postgresql://localhost:5432/mysticpaste jdbc.user=mysticpaste jdbc.password=password image.upload.path=/tmp/pasetbin/userimages image.upload.size.limit=4096K filters-PROD.properties jdbc.url=jdbc:postgresql://192.168.2.10:5432/mysticpaste jdbc.user=mysticpaste jdbc.password=CrYp71c image.upload.path=/mysticpaste/userimages image.upload.size.limit=4096K Now within any file under src/main/resources that has variables of the form ${variable.name} will have those variables replaced with the values specified in the proper filters file located under src/main/filters. For instance here is an example of a Spring applicationContext.xml file which will be interpolated with proper variables values at build time: applicationContext.xml To determine which filters file will be used depends on the profile chosen when building. For example, to build to production using the filters-PROD.properties we would execute the following: mvn clean deploy -P PROD The profile you use with the -P switch must match one of the values of the element for a profile. Conclusion Although it’s quite easy to get started with the Maven QuickStart project it is sometimes a bit frustrating putting some of the additonal pieces together. Building to several environments, setting up depenencies not included in the QuickStart project and strucuturing your project in an effort to make life easy for yourself as a developer and for your designer. I hope our Day 1 tutorial leaves you with a good sense of how a Wicket project is setup, now we can move onto coding the app! In the next four days we will be covering: Writing the Tests Designing the backend Designing the Wicket components Putting it all together Mystic Coders, LLC has been coding web magic since 2000. Mystic is a full-service Development Agency specializing in Enterprise development with Java. They are usually involved in developing enterprise-grade software for companies large and small, and have experience working in diverse industries, including b2b, b2c, and government-based projects. Mystic has done work with large companies such as LeapFrog, Nestlé, Harrah's Entertainment and the Los Angeles Conventions & Visitor's Bureau, among others. Andrew Lombardi, CTO of Mystic, is available for speaking engagements. For more about Mystic, check us out at http://www.mysticcoders.com
March 10, 2009
by Craig Tataryn
· 30,169 Views
article thumbnail
Pagination: Server Side or Client Side?
Numerous times in your projects you might have to face a situation where you need to pull chunks of data dynamically. The obvious issue that you then face is pagination\sorting and filtering. You then start to think if it would be better to handle it all at the server side or should hold back and handle it on the client side. Well there is no clear winner amongst the two; neither there is a right or wrong approach. The right answer depends on your priorities and the size of the data set to be paginated. If you have large number of pages doing it on client side will make your user download all the data at first which might not be needed, and will defeat the primary benefit of pagination. In such a scenario you are better of requesting pages in chunks from the server via AJAX. So let the server do the pagination. You can also pre-fetch the next few pages the user will likely view to make the interface seem more responsive. However, when implementing it, you need to make sure that you’re optimizing your SQL properly. For instance, I believe in MySQL, if you use the LIMIT option it doesn’t use the index so you need to rewrite your SQL to use the index properly. If there are only few pages, grabbing it all up-front and paginating on the client may be a better choice. That gives you the obvious benefit of faster subsequent page loads. Unless really required we should not choose the Server side pagination in such a case. Server side pagination is better for: Large data set Faster initial page load Accessibility for those not running JavaScript Complex view business logic Resilience to concurrent changes Client side pagination is better for: Small data set Faster subsequent page loads Sort & filter requirements supported fully (unless results greater than max size). To sum up, if you’re paginating for primarily cosmetic reasons, it makes more sense to handle it client side. And if you’re paginating to reduce initial load time, server side is the obvious choice. Of course, client side’s advantage on subsequent page load times diminishes if you utilize Ajax to load subsequent pages. for more information click here Comments\suggestions are welcome.
January 27, 2009
by Nitin Aggarwal
· 75,218 Views · 2 Likes
article thumbnail
Clearing Hibernate Second-Level Caches
Recently, I wanted to be able to clear out all of the Hibernate caches via JBoss's JMX console. I could have taken the easy way out; we're using EHCache, so it could have been as simple as calling CacheManager.clearAll(). However, that would have tied me to a specific cache provider. We're still evaluating switching to other cache providers. Ideally, my solution would not be dependent on a specific cache implementation. Hibernate's API does provide a simple way to clear specific caches, but does not provide any method for clearing out all of them. Writing your own is fairly straightforward. First, you obtain all of the entity and collection metadata from the session factory. Next you iterate over the entities, and if the object is cached, you clear out all of the caches associated with the persisted class or collection. Here's the code: @PersistenceContext private EntityManager em; public void clearHibernateCache() { Session s = (Session)em.getDelegate(); SessionFactory sf = s.getSessionFactory(); Map classMetadata = sf.getAllClassMetadata(); for (EntityPersister ep : classMetadata.values()) { if (ep.hasCache()) { sf.evictEntity(ep.getCache().getRegionName()); } } Map collMetadata = sf.getAllCollectionMetadata(); for (AbstractCollectionPersister acp : collMetadata.values()) { if (acp.hasCache()) { sf.evictCollection(acp.getCache().getRegionName()); } } return; } Now, if we decide to switch to a different cache provider, this code will not need to be re-written. Hopefully we won't ever change to a different JPA implementaion. :) From http://mikedesjardins.us/blog/
October 24, 2008
by Mike Desjardins
· 64,933 Views · 1 Like
article thumbnail
Enabling the Hover-Over-Help Feature Using JSP Custom Tags
This article introduces a presentation-tier JEE framework designed to enable the hover-over-help feature without hard coding JavaScript modules in the JSPs in your web or portal applications. The framework is packaged as a jar file for distribution and includes a server-side RESTful web service component and a set of JSP tag handlers which inserts JavaScript and Cascading Style Sheet (CSS) code into HTML files at the page rendering phrase. The targeted users are java developers who only have preliminary experience on writing JavaScript code. 1. Introduction Mouseover is a standard JavaScript event that is raised when the user hovers the cursor over a particular HTML element on a web page. This event has been widely used in web applications for navigation or causing an image or text to change. Hover-over-help, also called hover-over bubble, refers to the process of showing a small popup window when a mouseover event occurs in the browser. The window contains a message to either help the user to use the application or provide additional explanation and data. It is a useful feature which can make your web pages more intuitive and user-friendly and can carry more information on a single page in rich internet applications (RIAs). There are some tips and samples to enable the feature on the internet. However, they are not effective in developing large-scale web applications. Some of caveats include the following: The message contents are directly hard-coded in JavaScript. They are tied-coupled with graphic user interface components, such as text labels in web pages. The re-usability is low. If the same message needs to appear on several pages, the message and the pertaining JavaScript code have to be copied and pasted to each of these pages. It is hard to maintain these duplications in multiple places. The messages are designed to be static and are typically created when the page is designed. It is difficult to insert runtime data into messages on the fly. Portal applications are not completely supported. The framework introduced in this article is designed to address these issues and provides a comprehensive but easy-to-use solution to java developers who don’t have extensive JavaScript experiences. It leverages the JSP taglibary technology, the Dojo framework, and RESTful web services. Reusability in both web and portal environments, performance, and reliability are the factors that have been taken into consideration. 2. Message bubbles and messages 2.1 Message bubbles A message bubble is a rectangle information window containing a message. Each bubble has one color-coded title compartment and one content compartment. The window is decorated by CSS definitions. The image below illustrates a sample message bubble. Figure 1 – a hover-over-help message bubble Bubbles are not viewable in the webpage until the user moves his/her mouse over action labels or images. In this case, the mouse cursor will turn into a finger-pointing hand and the pertaining bubble window will pop up near the hand. 2.2 Data structure The message contents vary from static to dynamic considerably. However, all messages can share a common data structure, which typically consists of four parts: • Message ID: This is the primary key in each message, which is represented as a unique number. Given any single message ID, the framework is able to identify one and only one message. • Message title: This is a character string displayed in the title compartment in a bubble window. • Message content: This is character string that refers to the detail of a help message. The message content can contain HTML elements. • Color code: This is a character string representing the background color scheme of a bubble window. The value must be one of the following strings: “infor”, “data”, “warning”, or “link”. 2.3 Message types Based on the dynamicity of the contents, we categorized all messages into three types. Each of the types is described in this section, with samples provided. 2.3.1 Static Messages This type of message is considered static because its contents always retain the same. A static message can be the definition of a concept, the explanation of a field, or the instruction of a user action. The same messages will appear to any user on the same page when the page is visited. Valid examples include: • This is a example of a static message. • Click on the button below to submit your request. 2.3.2 Variable Messages These messages contain replaceable variables which are represented by tokens. A token is a non-whitespace character string surrounded by “${” and “}”. The token will be completely replaced by its actual value at the page rendering time on the server. The value is based on user data, and normally will not change for a longer-than-user-session period. From users’ perspectives, the same user will see the same message with his customized values when browsing the same page, but different users may see different messages. The following are examples of valid messages in this category: • Your first name ${firstname}. • Your annual goal is to sell ${yourgoalnumber} cars. 2.3.3 Dynamic Messages The messages in this category are the most dynamic ones and contain variables represented by tokens, as well. However, the actual values are populated based on the data associated to the user session. If it happens that a user session is shared by multiple applications, these values may be changed even without a page refresh. This situation typically occurs in portal applications where multiple portlets can access the same user session. It is possible that the same user will read different messages at a different time on the same page. The examples are – • You have talked to ${anumber} clients today. • It is ${servertimestamp} now. 3. Design and implementation In the design, messages are cached at server-side to gain the maximum performance. Two strategies have been implemented to support the hover-over-help feature for each of the message types described in the previous section. 3.1 Message caching Messages can be persisted in a database or flat text file, but regardless of where they are physically stored, they will be loaded and cached at the web container when it starts. The framework includes a class – CacheIntializer which implements the ServerContextListener interface to perform the job. All you need to develop is your own message loader class to retrieve your messages from storage. Your class must implement the com.myuan.tags.bubblemsg.serverside.MessageLoader interface in the framework, and its name must be added as a ContextParameter in the web descriptor. Please refer to the installation section for more details. 3.2 Dojo and CSS Strategy This strategy is designed to support static and variable messages. It can be referred as the push strategy, since help messages are embedded as html elements and pushed to users’ browsers along with the whole web page. No client-server communication is needed once the page download is done. The values will be kept the same until the page is re-loaded again. This strategy relies on a Dojo module to recognize particular “span” elements (listed in list 1) in html files. For each individual message bubble, two span elements are required. The first one represents a visible graphical component in a page, while the second one is the message bubble which isn’t visible for most of the time. When you move the mouse over the first “span” area, an action will be triggered by the browser, and a Dojo method will make the message bubble popped up (illustrated in Figure 1). The “id” attribute in the first “span” element and the “connectid” attribute in the second one are the keys to tie the pair together. These two attributes must have the same value. The value is randomly generated by the custom tags in the framework, which guarantees that the strategy can support both web and portal applications. Households Household A household includes all the persons who occupy a housing unit. Four tag handlers have been developed to support static message and variable message scenarios, respectively. At page-rendering time, the handlers can retrieve help messages from the cache, replace variable tokens in the messages if any, and create and insert value-matched “span” html elements into the web pages. The complete process is detailed in the sequence diagram in figure 2. Figure 2 – sequence diagram for the Dojo and CSS strategy 3.2.1 hohcsstag This tag inserts CSS definitions in JSP pages at the rendering time. It should be placed in the page head element. In the WebSphere Portal environment, this tag should be added in the Default.jsp file. 3.2.2 hohstatictag hohstatictag is a custom tag built for the static message scenario. It has five attributes: msgid: This is the primary key used to identify a message from the cache. This attribute is mandatory. label: This is the text which will be associated with a mouse-over action to display the message. style: This is the style definition that will be used to decorate the label above. This is the place where the user could overwrite CSS arributes for the label. bubblestyle: This is the place where the user could overwrite CSS attributes for the message bubble. img: If you need to enable the hover-over on an image instead of a text label, you can use this attribute and pass the path to your image. If this attribute appears in the tag, the value in the “label” and the “style” attributes will be ignored. A static message example -- Msg_id Msg_title Msg_content Color_cd 1 Household A household includes all the persons who occupy a housing unit. Infor JSP Fragment where the hohstatictag is used – //text //image 3.2.3 hohvariabletag and hohparamtag hohvariabletag and hohparamtag work together to support variable messages. The “hohvariabletag” has the same four attributes as the “hohstatictag” tag. One “hohparamtag” tag holds one name-value pair. The tokens in the message will be replaced with the values passed in from the hohparamtag when html elements are generated. The following is an example of how to use the custom tag. A variable message example-- Msg_id Msg_title Msg_content Color_cd 2 Recognition My retention rate is ${rate} and my goal is ${goal}. data JSP Fragment where the hohvariabletag and hohparamtag are used together – 3.2.4 hohgenerictag This tag has been created to provide a unified API for both static and variable messages. This tag can replace the “hohstatictag” or “hohvariabletag” without any syntax change. But there will be a minor performance cost if you use this tag on the static-message scenario instead of the hohstatictag. 3.3 AJAX strategy AJAX (Asynchronous JavaScript and XML) is a powerful web development technique in creating interactive web applications. The AJAX strategy was developed for the dynamic message scenario. It is a pull-based model, since messages are retrieved by an AJAX module at runtime from the server. This approach can guarantee that the message contains the latest data. When a mouseover event is triggered from a web page, the AJAX module invokes the server-side RESTful web service endpoint. The server-side component picks up the correct message from the message cache, replaces all variable tokens in it with the most current user-session data, and sends the final message back to your browser in the XML format. Upon receiving the response, the AJAX module populates the pertaining information window and pops it up. The complete process is illustrated in the sequence diagram in figure 3. Figure 3 – Sequence diagram for the AJAX strategy One servlet class and three custom tags have been created to support this strategy, and they must be used together in the same page. 3.3.1 HelpMessagesServiceServlet This is an extension of the HTTPSerlvet class. It serves as the RESTful web service endpoint at the server-side. It processes the HTTP request from the client-side AJAX module, constructs the message with the latest data in user’s session, and sends the response in XML format back to the browser. A sample response is listed below. Household infor Household A household includes all the persons who occupy a housing unit. 3.3.2 hohajaxtag This tag inserts AJAX methods in a JSP which will be invoked by the hohdynatag below. It has two attributes. The namespace can be used to pass a portlet’s namespace into the tag in the portal environment. In a web application the value of the attribute can be left blank. The serviceurl attribute must be the valid URL for the HelpMessagesServiceServlet. In the WebSphere Portal environment, this tag should be added in the Default.jsp file. // Portal environment // Web environment 3.3.3 hohdynatag and hohdynaparamtag The hohdynatag has four attributes as same as the “hohstatictag” tag, and it will generate a “span” element. Each hohdynaparamtag establishes a mapping between one token in the message and one key used in user’s session to refer to the actual value. These mappings will be sent to the RESTful endpoint as HTTP parameters. When a user’s mouse moves over the area in a page represented by the span tag, the following events will occur sequentially at the client’s browser: • OnMouseOver events will be fired by the browser. • The Ajax method generated by the hohajaxtag will be invoked. The method will make an HTTP request to the RESTful service endpoint and will be waiting for the response. • Upon receiving the response, the AJAX method will parse it to get the actual help message. • The AJAX method will display the message bubble in the browser. Below is a valid utilization of these tags. 4. Installation The installation procedure is fairly straight forward. After adding the jar file – MYTagLib.jar -- into the /WEB-INF/lib directory in your web project, you can use the deployment descriptor editor in RAD/RSA to complete the installation: Develop your own message loader class and add a context parameter with the name “BubbleMsgLoaderClass” and the value as the fully qualified name of your class. Figure 4 – adding your class name as a Server Context Parameter Create a listener. The class name is: com.myuan.tags.bubblemsg.serverside.CacheInitializer, and the class is shipped in the TagLib.jar file. Figure 5 – creating the listener with the shipped class Add the servlet class in the framework into the deployment descriptor in your web project. The servlet class is also shipped in the MYTagLib.jar. Figure 6 – creating a servlet with the shipped class Define the taglib element in the /WEB-INF/web.xml file. Figure 7 – adding the tag lib references Define the tag extension in your JSP pages. The and the uri directive must match. The prefix identifies the tags in the tag library within the jsp page. For example: 5 Conclusion The framework packaged in the MYTagLib.jar can enable the hover-over-help feature in a web or portal application without adding any JavaScript/CSS code into JSP pages during the development phrase. This approach can make it simpler to create and maintain these pages. The framework has been tested in web applications running on WebSphere Application Server (WAS) 6.0 and 6.1, as well as in portal applications running on WebSphere Portal 5.1 and 6.0.
October 21, 2008
by Ming Yuan
· 39,568 Views · 1 Like
article thumbnail
Importing XML Data Into A SQLite Table
For inserting into a SQLite table, use the code as follows: //DB Connection private var dbconn:SQLConnection; //Query Statement private var sqlQuery:SQLStatement; //Create Table Statement private var sqlCreateTable:SQLStatement; //Insert Statement private var sqlInsert:SQLStatement; //Import Statement private var sqlImport:SQLStatement; /** * This is for importing xml data to a SQLite table * @param node xml node * @param user the user whos data this is * */ public function importPostXML( node:XMLNode, user:User ):void { var query:String = "INSERT INTO posts (" + "post_url," + "post_hash," + "post_desc," + "post_tags," + "post_time," + "post_extended," + "post_shared," + "post_replace," + "post_user)" + "VALUES ( " + ":post_url," + ":post_hash," + ":post_desc," + ":post_tags," + ":post_time," + ":post_extended," + ":post_shared," + ":post_replace," + ":post_user)"; sqlImport = new SQLStatement(); sqlImport.sqlConnection = dbconn; sqlImport.addEventListener( SQLEvent.RESULT, onSQLSave ); sqlImport.addEventListener( SQLErrorEvent.ERROR, onSQLError ); sqlImport.text = query; sqlImport.parameters[":post_url"] = node.attributes.href; sqlImport.parameters[":post_hash"] = node.attributes.hash; sqlImport.parameters[":post_desc"] = node.attributes.description; sqlImport.parameters[":post_tags"] = node.attributes.tag; sqlImport.parameters[":post_time"] = node.attributes.time; sqlImport.parameters[":post_extended"] = node.attributes.extended; sqlImport.parameters[":post_shared"] = node.attributes.shared; sqlImport.parameters[":post_replace"] = node.attributes.replace; sqlImport.parameters[":post_user"] = user.user_name; sqlImport.execute(); trace( "Importing XML to SQLite Database" ); }
September 21, 2008
by Jonnie Spratley
· 15,904 Views · 1 Like
article thumbnail
Reverse-Engineer Source Code into UML Diagrams
This article shows how easy and simple it is to include UML diagrams within your Javadoc and also keep them updated with every change in the source code repository.
August 22, 2008
by Meera Subbarao
· 220,879 Views · 1 Like
article thumbnail
LINQ: Folding Left, Right And The LINQ Aggregation Operator
Discussion of functional programming concepts, focusing on fold operations and their implementation in C# using LINQ and expression trees.
August 18, 2008
by Bart De Smet
· 10,308 Views
  • Previous
  • ...
  • 430
  • 431
  • 432
  • 433
  • 434
  • 435
  • Next
  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook
×