JavaBeat

  • Home
  • Java
    • Java 7
    • Java 8
    • Java EE
    • Servlets
  • Spring Framework
    • Spring Tutorials
    • Spring 4 Tutorials
    • Spring Boot
  • JSF Tutorials
  • Most Popular
    • Binary Search Tree Traversal
    • Spring Batch Tutorial
    • AngularJS + Spring MVC
    • Spring Data JPA Tutorial
    • Packaging and Deploying Node.js
  • About Us
    • Join Us (JBC)
  • Privacy

BIRT 2.6 Data Analysis and Reporting

October 9, 2010 by itadmin Leave a Comment

BIRT 2.6 Data Analysis and Reporting

BIRT is an open source business intelligence and reporting tool, built on top of the Eclipse Framework. BIRT is used by developers for building reports that can best represent data and tell a story of that data that is easy to follow. In addition, BIRT can be integrated into a product, to allow that product to provide reporting capabilities. This book will walk the user through the basics of building reports with BIRT and introduce them to the various sections of the BIRT environment.

also read:

  • Java Tutorials
  • Java EE Tutorials
  • Design Patterns Tutorials
  • Java File IO Tutorials

What This Book Covers

Chapter 1, Getting Started, is an introduction to BIRT. It gives the reader an idea of the BIRT features, community landscape, and the various websites out there that are dedicated to BIRT.
Chapter 2, Installing BIRT, guides the user through the various ways of installing BIRT.
Chapter 3, The BIRT Environment and First Report, introduces the BIRT workspace environment by walking the reader through a simple report example.
Chapter 4, Visual Report Items, presents us with various visual report items that are available for use in a report design.
Chapter 5, Working with Data, discusses how to retrieve data from databases, fl at text files, web services, and other data sources.
Chapter 6, Report Parameters, explains how to get input from the report user, along with how to apply these report parameters in filtering data.
Chapter 7, Report Projects and Libraries, looks at reusing report sections and sharing resources through libraries and report projects.
Chapter 8, Charts, Hyperlinks, and Drilldowns, shows how to build summary data using charts and linking sections of charts to reports. In addition, hyper linking used in online reports to link and show detailed data in other reports is discussed here.
Chapter 9, Scripting and Event Handling, discusses report generation through event handling, as well as how to manipulate and format data using simple JavaScript expressions. Some advanced scripting examples are provided based on common requests.
Chapter 10, Deployment, looks at how does a developer can get reports out into the world for consumption.

Charts, Hyperlinks, and Drilldowns

It has been said that a picture is worth a thousand words. In the world of reporting, we call these pictures as Charts. With the help of charts, one can present a large amount of data with relative ease, in comparison to presenting with the help of huge data outputs. Charts are useful when used with raw data to drive home points such as percentages, or when used with other charts to build dashboards.
BIRT has an exceptional charting engine. BIRT can create a number of different Chart types, including the tried and tested pie chart, bar chart, and line charts. In addition, there are several other chart types that were extras to BIRT’s commercial counterpart such as the Meter Chart and Gantt chart.
In the following sections, we are going to look at building a few different charts centered around employee sales performance. First, we will build a pie chart that will illustrate the top employees based on sales. We will then create a gauge chart that will show the progress an employee has made to meet a quota. Finally, we will create a bar chart that will show sales performance for employees across a time period.

Pie chart

In the following exercise, we are going to look at how to build a pie chart. A pie chart is a very common report type used in business to display percentages. In this example, we will create a pie chart to show what percentage an employee contributed to the total amount of sales. This will give us a visual representation of who the top employees are in terms of sales.

  1. Create a new report titled Employee_Sales_Percentage.rptDesign.
  2. From the ClassicCarsLibrary.rptDesign library, add the dsClassicCarsdata source to the report.
  3. Create a new dataset called totalSales using the following query:
  4. [code]
    select
    CLASSICMODELS.EMPLOYEES.EMPLOYEENUMBER,
    CLASSICMODELS.EMPLOYEES.LASTNAME || ‘, ‘ || CLASSICMODELS.
    EMPLOYEES.FIRSTNAME name,
    sum(CLASSICMODELS.ORDERDETAILS.PRICEEACH) sales
    from
    CLASSICMODELS.EMPLOYEES,
    CLASSICMODELS.ORDERS,
    CLASSICMODELS.ORDERDETAILS,
    CLASSICMODELS.CUSTOMERS
    where
    CLASSICMODELS.CUSTOMERS.SALESREPEMPLOYEENUMBER =
    CLASSICMODELS.EMPLOYEES.EMPLOYEENUMBER
    and CLASSICMODELS.ORDERS.CUSTOMERNUMBER = CLASSICMODELS.
    CUSTOMERS.CUSTOMERNUMBER
    and CLASSICMODELS.ORDERDETAILS.ORDERNUMBER = CLASSICMODELS.
    ORDERS.ORDERNUMBER
    and CLASSICMODELS.ORDERS.ORDERDATE between ? and ?
    group by
    CLASSICMODELS.EMPLOYEES.EMPLOYEENUMBER,
    CLASSICMODELS.EMPLOYEES.LASTNAME,
    CLASSICMODELS.EMPLOYEES.FIRSTNAME
    [/code]

  5. Create two report parameters called startDate and endDate as date types and link them to the two report parameters. Use 2005-01-01 as the startDate’s default value, and 2005-05-01 as the endDate’s default value.
  6. Drag a chart component from the Palette to the Report Designer.
  7. In the Chart dialog, select Pie chart. Change the Output format from SVG to PNG. Typically, iuse either PNG or JPEG, as SVG is not a universally
    supported format. However, SVG does have a distinct advantage over both PNG and JPEG in that SVG images are smaller in size due to the format’s vector nature.
  8. Open the Select Data tab. Under the Select Data section, select Use Data Set and choose the totalSales dataset.
  9. We can drag the column headers from the dataset to the slice definitions. Drag the SALES column to the Slice Size Definition and the NAME column to the Category Definition. To make selecting the correct header easier, we can use the Show data preview checkbox to see what data is in each column. Without it, the preview box will show only the column names.
  10. Select the Format Chart tab. Under the Title section, enter Employee Sales
    Percentages
    as the chart title. In this editor, we change how the chart looks and feels.
  11. Click Finish.
  12. Resize the chart to take up report page. This can be done by dragging the corner of the chart or by entering the height and width values in the property editor.
  13. The chart will look something like the following screenshot when previewed:


So, we have built a fairly simple report so far. This report is a pie chart with a legend
that shows us the employee’s color code, with an excerpt that shows us the value of that slice.

Pie chart with explosions

While the pie chart we saw in the preceding section is nice, it would be a little easier
to view if the slices were exploded, and if the slices had an outline. Let’s take a look
at how to modify some of the chart’s properties to do this.

  1. Double-click on the chart in the report design. This will reopen the chart dialog. Another option is to right-click on the chart and choose Format Chart….
  2. Open the Format Chart… tab.
  3. Open the Value Series section.
  4. Under the Slice section, change the By Distance value to 6.
  5. For Slice Outline, choose the color black from the palette.
  6. Save the chart and preview it. The following screenshot shows what the chart
    looks like with the explosion and slice outline added.

Pie charts—working with percentages

Things are starting to look better. But let’s say we want to change the chart to display
percentages instead of numbers and add a little interactivity to the chart to display the sales numbers when a section is clicked on.

  1. Double-click on the chart to edit it.
  2. Select the Value Series section.
  3. Click on the Labels button.
  4. Under Values, remove the Value Data option.
  5. Under Values, add Percentile Value Data.
  6. Click the Interactivity button.
  7. Choose Mouse Click from the Event listbox.
  8. From the Action listbox, choose Invoke Script.
  9. Click the Expression Editor button.
  10. Using the editor, click on the Variables | Chart Data Point | Value Data option to insert the valueData variable into the editor. Surround it with an alert() method call. It should look like the next screenshot:
  11. Click OK. Now click on the << arrows in the Series Interactivity window.
  12. Click Finish in the Chart Editor.

When we preview the report, the chart pops up, formatted in the manner we want. If we click on one of the pie slices, an alert window will pop up showing the value for that series.

Gauge chart

With the next chart, the guage chart, we will expand on the interactivity a bit and demonstrate how drill-downs work. In addition to viewing the static chart, we want the user to be able to click on the chart and have it pull up an external report with the details for a particular user. This is called a drilldown.

The following meter chart will demonstrate an employees sales vs. a target amount per month, let’s say 3000, on a 5000 dollar scale. This will be broken out and grouped monthly in the query statement. When the user clicks on the chart, it will bring them to the detail report we created last chapter for Employee sales.

  1. Create a new report titled Employee_Sales_Guage.rptDesign.
  2. From the library, drag over the dsClassicCars data source.
  3. Create a new dataset called employeeSales using the following query:
  4. [code]
    select
    CLASSICMODELS.EMPLOYEES.EMPLOYEENUMBER,
    CLASSICMODELS.EMPLOYEES.LASTNAME || ‘, ‘ || CLASSICMODELS.
    EMPLOYEES.FIRSTNAME name,
    sum(CLASSICMODELS.ORDERDETAILS.PRICEEACH) sales,
    rtrim(char(year(CLASSICMODELS.ORDERS.ORDERDATE))) || ‘-‘ ||
    rtrim(char(month(CLASSICMODELS.ORDERS.ORDERDATE))) orderDate
    from
    CLASSICMODELS.EMPLOYEES,
    CLASSICMODELS.CUSTOMERS,
    CLASSICMODELS.ORDERS,
    CLASSICMODELS.ORDERDETAILS
    where
    CLASSICMODELS.ORDERS.ORDERNUMBER = CLASSICMODELS.
    ORDERDETAILS.ORDERNUMBER
    and CLASSICMODELS.EMPLOYEES.EMPLOYEENUMBER = CLASSICMODELS.
    CUSTOMERS.SALESREPEMPLOYEENUMBER
    and CLASSICMODELS.ORDERS.CUSTOMERNUMBER = CLASSICMODELS.
    CUSTOMERS.CUSTOMERNUMBER
    and CLASSICMODELS.ORDERS.ORDERDATE between ? and ?
    group by
    year(CLASSICMODELS.ORDERS.ORDERDATE),
    month(CLASSICMODELS.ORDERS.ORDERDATE),
    CLASSICMODELS.EMPLOYEES.EMPLOYEENUMBER,
    CLASSICMODELS.EMPLOYEES.LASTNAME,
    CLASSICMODELS.EMPLOYEES.FIRSTNAME
    [/code]

  5. Link the two dataset parameters to the report parameters, startDate and endDate respectively.
  6. Drag the employeeSales dataset to the report designer.
  7. Delete the last two columns from the table.
  8. Create a group called GroupByEmployee in the table and set it to group on the EMPLOYEENUMBER.

  9. Create another group below GroupByEmployee and call it groupByDate. Set it to group on the ORDERDATE field.
  10. Merge all of the cells in the orderDate details row into one large cell. Be sure to delete any data items that are still present such as the NAME and EMPLOYEENUMBER items.
  11. In the new large cell, create a chart element.
  12. Select Meter as the type, and select SuperImpose Meter as the chart type. If we need to know which type of chart we are picking, hover the mouse over the chart for a second and its description will pop up. Set the Output Format
    to PNG.
  13. In the Select Data tab, create another dial by selecting the Meter Value Definition drop-down list and selecting <New Series..>.
  14. For the expression for Dial 1, select row[“SALES”] by either dragging the column over from the Data Preview pane or by using the Expression Editor.
  15. The value for Dial 2 should be set to 3000.
  16. As Category Definition, use row[“NAME”] by either dragging the column over from the Data Preview section or using the Expression Editor.
  17. In the Format Chart tab, under the Value Series section, click the Scale button.
  18. Enter 0 for the Min value and 5000 for the Max value. We have now set up the scale.
  19. On the Edit Chart tab, under the Legend section, uncheck the Visible checkbox.
  20. Select Chart Area.
  21. Click the Interactivity button.
  22. Select Mouse Click from the Event listbox and select Hyperlink from the Action listbox.
  23. Click the Add Button.
  24. In the Name field, insert NewHyperlink.
  25. Click the Edit Base URL… button.
  26. Select Drill-through as the hyperlink type.
  27. For the Report Design, navigate and select the report Employee Sales Details Report.rptDesign. This report was created in the preceding chapter.
  28. Select the startDate and endDate parameters under the Parameters drop down, which selects the parameters in the target report. Under Values, enter params[“startDate”].value and params[“endDate”].value, or whatever names that have been used used for the current report’s startDate and endDate parameters.
  29. Under Step 2, select Target Bookmark. From the drop-down list, select row[“EmployeeNumber”].
  30. Under Step 4, select New Window.
  31. We can skip Step 5 as we are sticking to our default output format, which is HTML. We could have the target report open in any format that we have an emitter registered for. Emitters are plugins for BIRT that produce output in different formats such as HTML, PDF, Microsoft Excel, or Microsoft Word.
  32. Click OK to exit the dialog and save the report.
  33. Delete the table header.
  34. Delete the EMPLOYEENUMBER data element.
  35. Drag the EMPLOYEENUMBER column from the Data Explorer, next to the OrderDate report item.
  36. Now run the report. When we click on any of the charts, a detailed report will open and the control will automatically jump to the employees section, as specified in the Bookmark in the target report.

Of course, this example can be heavily modified to simplify things. The charts could be consolidated into single chart, with more needles for each month instead of separate charts for each month, by moving the chart into the EmployeeNumber group’s header or footer row and adding a group by date in the chart editors dialog under the Select Data tab. It is also possible to make the needles interactive and to filter down to a specific user and date range by modifying the bookmarks in the target report, but I will leave that up to the reader to discover. The following is a modified version of the the report that has created different series in the chart itself for the date groupings.

Bar chart

In the earlier section, we saw some of the power that charting can have with reports,by adding both the graphical representation of data and the interactivity for users to see the details of that data in a separate report. We also saw how to pass data through to the target report by using the expression. In this report, the hyperlink will take us to an internal bookmark, which means it will jump us to a location inside the same report containing the details for our report. We will also look at aggregating values inside the chart so that we can provide a simple query that just retrieves the necessary details and lets BIRT handle the tricky stuff for us.

  1. Create a new report called EmployeeSalesPerformanceReport.rptDesign.
  2. Use the dsClassicCars data source in the library.
  3. Create a new dataset called employeeSales, using the following query:
  4. [code]
    select
    CLASSICMODELS.EMPLOYEES.EMPLOYEENUMBER,
    CLASSICMODELS.EMPLOYEES.LASTNAME || ‘, ‘ || CLASSICMODELS.
    EMPLOYEES.FIRSTNAME name,
    CLASSICMODELS.ORDERDETAILS.PRICEEACH,
    CLASSICMODELS.ORDERS.ORDERDATE,
    CLASSICMODELS.PRODUCTS.PRODUCTNAME
    from
    CLASSICMODELS.EMPLOYEES,
    CLASSICMODELS.CUSTOMERS,
    CLASSICMODELS.ORDERS,
    CLASSICMODELS.ORDERDETAILS,
    CLASSICMODELS.PRODUCTS
    where
    CLASSICMODELS.ORDERS.ORDERNUMBER = CLASSICMODELS.
    ORDERDETAILS.ORDERNUMBER
    and CLASSICMODELS.EMPLOYEES.EMPLOYEENUMBER = CLASSICMODELS.
    CUSTOMERS.SALESREPEMPLOYEENUMBER
    and CLASSICMODELS.ORDERS.CUSTOMERNUMBER = CLASSICMODELS.
    CUSTOMERS.CUSTOMERNUMBER
    and CLASSICMODELS.PRODUCTS.PRODUCTCODE = CLASSICMODELS.
    ORDERDETAILS.PRODUCTCODE
    and CLASSICMODELS.ORDERS.ORDERDATE between ? and ?
    [/code]

  5. Map the dataset parameters to report parameters startDate and endDate.
  6. Drag a table element over from the palette.
  7. Set Number of columns to 3 and Number of details to 1, and map the
    dataset element to the employeeSales dataset.
  8. In the header row, insert a new row.
  9. In the top most header, merge all the cells into one large cell.
  10. Insert a chart element into the large cell.
  11. Select Bar chart as the type.
  12. Select the stacked Bar Chart as the subtype.
  13. Set the Output Format to PNG.
  14. Go to the Select Data tab.
  15. For the series value, drag in the PRICEEACH column.
  16. For the Category (x) Series, use the following expression:
  17. [code]
    (row["ORDERDATE"].getYear() + 1900).toString() + ‘-‘ +
    (row["ORDERDATE"].getMonth() + 1).toString()
    [/code]

    This may not make much sense now, but we will explain it further in the next chapter.

  18. For the Optional Y Series Grouping, drag in the NAME column.
  19. In the Inherit Data From Container drop-down list, select Inherit Columns only. This will set up the chart to ignore any grouping at the table level and let the chart engine do its down grouping.
  20. Next to the Category (x) Series expression editor button , there is a button to
    edit group and sorting. Click that button.
  21. Select Ascending from the Data Sorting drop down.
  22. In the Grouping checkbox, check the Enable option.
  23. Keep the other values at their defaults and click OK.
  24. Click Finish and save the report.
  25. Select the table, and create a group on EMPLOYEENUMBER.
  26. Create a grouping on OrderDate.
  27. For the detail row, drag over the PRODUCTNAME into the second column and PRICEEACH into the third column.
  28. From the Palette, drag over an Aggregation element into the groupFooter
    for the OrderDate grouping.
  29. Create the aggregation on the PRICEEACH field for the salesDateGroup.
  30. Add in any formatting that might spruce up the look of our report.
  31. Select the OrderDate groupings header row . Select the Bookmark tab under the property editor. Use the following expression for the bookmark:
  32. [code]
    row["EMPLOYEENUMBER"] + row["ORDERDATE"]
    [/code]

  33. Double-click on the chart to enter the Chart Editor.
  34. Select the Format Chart tab.
  35. In the Edit Chart window, select the Value (Y) Series section and click the
    Interactivity button.
  36. In the Event drop-down list select Mouse Click, whereas in the Action
    listbox select Hyperlink.
  37. Click the Add button.
  38. Enter ChartHyperlink for the Name.
  39. Click the Edit base URL… button.
  40. In the hyperlink dialog box, select Internal Bookmark as the type.
  41. Select the following from the drop down:
  42. [code]
    row["EMPLOYEENUMBER"] + row["ORDERDATE"]
    [/code]

  43. Click OK to save the report. Now run it.

Now, when we click on any of the different colored sections of the bar chart, it will bring us to the details section within our own report.

Summary

In this chapter, we have seen how to create several different chart types. We have seen how we can create interactivity within a single report and how to drill down into a separate report using charts and passing through parameters. We have seen how to aggregate data within a chart to serve as a summary for the more detailed data. We have opened the dialog to edit properties of charts and seen how a few of the properties affect the look and feel of charts as well as the behavior.
In the next chapter, we are going to explore the basic of scripting in BIRT reports.
Throughout this book we have been using a basic type of script called an expression. We will explore this in following chapters and expand into event handling as well.

Filed Under: Java Tagged With: Java Reports

Groovy for Domain-Specific Languages

October 8, 2010 by itadmin Leave a Comment

Groovy for Domain-Specific Languages

The Java virtual machine runs on everything from the largest mainframe to the smallest microchip and supports every conceivable application. But Java is a complex and sometimes arcane language to develop with. Groovy allows us to build targeted single purpose mini languages, which can run directly on the JVM alongside regular Java code. This book provides a comprehensive tutorial on designing and developing miniGroovybased Domain-Specific Languages. It is a complete guide to the development of several miniDSLs with a lot of easy-to-understand examples. This book will help you to gain all of the skills needed to develop your own Groovy-based DSLs.
Groovy for Domain-Specific Languages guides the reader from the basics through to the more complex meta-programming features of Groovy. The focus is on how the Groovy
language can be used to construct domain-specific minilanguages. Practical examples are used throughout to demystify these seemingly complex language features and to show how they can be used to create simple and elegant DSLs. The examples include a quick and simple Groovy DSL to interface with Twitter.
The book concludes with a chapter focusing on integrating Groovy-based DSL in such a way that the scripts can be readily incorporated into the reader’s own Java applications. The overall goal of this book is to take Java developers through the skills and knowledge they need to start building effective Groovy-based DSLs to integrate into their own applications.

also read:

  • Groovy Tutorials
  • Creating JSON using Groovy
  • Developing Groovy based web application and deploying to Google App Engine

What This Book Covers

Chapter 1, Introduction to DSL and Groovy, discusses how DSLs can be used in place of general-purpose languages to represent different parts of a system. You will see how adding DSLs to your applications can open up the development process to other stakeholders in the development process. You’ll also see how, in extreme cases, the stakeholders themselves can even become co-developers of the system by using DSLs that let them represent their domain expertise in code.
Chapter 2, Groovy Quick Start, covers a whistle-stop tour of the Groovy language. It also touches on most of the significant features of the language as a part of this tour.
Chapter 3, Groovy Closures, covers closures in some depth. It covers all of the important aspects of working with closures. You can explore the various ways to call a closure and the means of passing parameters. You will see how to pass closures as parameters to
methods, and how this construct can allow us to add miniDSL syntax to our code.
Chapter 4, Example DSL: GeeTwitter, focuses on how we can start with an existing Javabased APiand evolve it into a simple user-friendly DSL that can be used by almost anybody. You’ll learn the importance of removing boilerplate code and how you can structure our DSL in such a way that the boilerplate is invisible to our DSL users.
Chapter 5, Power Groovy DSL Features, covers all of the important features of the Groovy language, and looks in depth at how some of these features can be applied to developing DSLs.
Chapter 6, Existing Groovy DSLs, discusses some existing Groovy DSLs that are in current use and are free to download.
Chapter 7, Building a Builder, explains how Groovy provides two useful support classes that make it much simpler to implement our own builders than if we use the MOP. You’ll see how to use BuilderSupport and FactoryBuilderSupport to create our own builder classes.
Chapter 8, Implementing a Rules DSL, takes a look at Groovy bindings to see how they can be used in our DSL scripts. By placing closures strategically in the binding, you can emulate named blocks of code. You can also provide built-in methods and other shorthand by including closures and named Boolean values in the binding. These techniques can be used to a great effect to write DSL scripts that can be read and understood by stakeholders outside of the programming audience.
Chapter 9, Integrating it all, covers the many different ways in which you can integrate Groovy code into Java. You’ll explore the issues around tightly integrating the two languages at compile time. You’ll see how this can lead to dependency issues arising
when Java code references Groovy classes and vice versa. You’ll take a look at how you can use dependency injection frameworks like Spring to resolve some of these issues.

Building a Builder

Builders are a powerful feature of Groovy. The Groovy libraries contain an expanding set of Builders for everything from XML and HTML markup to managing systems via JMX. Even so you will always come across circumstances where the semantics of a builder would be useful in your own application. We’ve seen how to build a rudimentary builder by using the Groovy MOP and pretended methods in Chapter 5. Thankfully, the Groovy libraries provide us with easier means of developing our own builders. In this chapter, we will look at some of the ways in which we can use Groovy and the MOP to create our own builder classes.


  • To begin with, we will recap the Groovy features that enable the Groovy builder pattern in order to understand how they work.

  • We will look at how to build a rudimentary builder with features from the Groovy MOP.

  • We will implement our own database seed data Builder by using two of the builder support classes provided in Groovy: BuilderSupport and FactoryBuilderSupport.

Builder code structure

The real beauty of Groovy‘s builder paradigm is the way in which it maps the naturally nested block structure of the language to the construction process. The process of defining parent-child relationships between objects through nested code blocks is well-established through other markup languages, such as XML and HTML.
The transition from writing XML or HTML to the GroovyMarkup equivalent is an easy one. To make use of a builder, we don’t need to have any intimate understanding of the Groovy MOP or of how the builder is implemented. We just need to know how to write the builder code so that it conforms to the correct language semantics. The code structure of the builder pattern relies on just a few Groovy language features.


  • Closure method calls: The distinctively nested block structure in the builder pattern is facilitated by Groovy‘s special handling of closures when they are passed as method parameters. This allows the closure block to be declared inline after the other method call parameters.

  • Closure method resolution: When a method is invoked within the body of a closure and that method does not exist in the closure instance, Groovy uses a resolve strategy to determine which object (if any) should be tried to locate that method.

  • Pretended methods: The Groovy MOP allows us to respond to method calls that do not exist in a class—in other words to “pretend” that these methods exist.

  • Named parameters: When we pass a map parameter to a method, we can declare the individual map elements alongside the other method parameters, giving the effect of a named parameter list.

  • Closure delegate: Changing the delegate of a closure allows another class to handle its method calls. When we change the delegate to a builder class, this allows the builder to orchestrate how the method calls are handled.


Closure method calls


When we declare a Groovy method that accepts a closure as its last parameter, Groovy allows us to define the body of the inline closure immediately after the method call containing the other parameters. A method call followed by an inline closure block has all the appearance of being a named block of code. It’s when we nest these method calls within each other that we get the distinctive builder-style code blocks.
This style of coding is not unique to builders. We can nest other method calls in the same way. In the following example, we have three methods defined within a script: method1(), method2(), and method3(). Nesting calls to these methods gives us some code that is very similar to a builder block, but is not actually a builder block.
The cool thing about the builder pattern is that it uses this existing feature from the language and turns it into a whole new coding paradigm.

The success of building our own b uilder class by using the Groovy MOP depends largely o n understanding the sequence in which these methods get called. The output gives us an idea of what might be happening and what the true sequence of events is. Let’s decorate the code a little to show what is happening. The comments show what scope we are running in.
[code]
// Script scope
method1(param: "one") { // Closure1 scope
method2 { // Closure2 scope
method3 "hello"
} // End Closure2
method1( 123 ) { // Closure3 scope
method1 ( "nested" ) { // Closure4 scope
method3 10
} // End Closure4
} // End Closure3
} // End Closure1
[/code]
The main block of code runs within the scope of the script. Each inline closure is in fact an anonymous instance of a C losure object. For the purpose of this exercise we will name these instances Closure1 to Closure4. The first call to method1() occurs in the outer scope of the script so we would expect this method to be passed to the script instance. The subsequent method calls all happen within the scope of one or other of the anonymous closure instances, so we expect these methods to be invoked on the individual closure instances. The following sequence diagram illustrates this:

Resolve Strategy: OWNER_FIRST


The one problem with the previous diagram is that we know that the closure instances don’t implement the method1() t o method3() methods. So this sequence diagram shows what methods are initially called, but it does not show what methods actually get called. When Groovy makes a call to a method on a closure, it does not always expect it to be present.
If a method is not present in the closure itself, Groovy will try to find it by looking in the owner of the closure, or its delegate, or both. The order in which this occurs is called the resolve strategy of the closure. The default resolve strategy is OWNER_FIRST, which means that the owner of the closure will be queried first for the method, followed by the delegate. If the owner of the closure happens to be another closure, then the resolve strategy will continue its search for a match in the owner of the owner and so on, until a match is found or the outer scope is reached.

The resolve strategy can be changed for a closure by calling Closure.setResolveStrategy. We can change the resolve strategy to any of the following self-explanatory strategies: OWNER_FIRST, OWNER_ONLY, DELEGATE_FIRST, DELEGATE_ONLY, and NONE.

Although the preceding sequence diagram refl ects the first port of call for each method invocation, what in fact happens is that the resolve strategy kicks in and the method calls will percolate out through the closure instances. A match will eventually be found in the script instance, which is the only place where the actual methods exist. Therefore, the actual calling sequence is better represented as follows:

The insight that Groovy designers had when designing the builder pattern was that this natural nesting of closures could be used to map to any construction process that involved a parent-child type of relationship. Even without using a builder class, we can nest closures’ method calls to create a pseudo builder. In the next example, we declare three methods that we can use to construct a rudimentary tree structure out of map objects.
The root() method creates the initial tree map and inserts a root element into it. We can nest as many levels deep as we like with the nod e() method, as it will remember its parent node and add sub nodes to it. The leaf() method is the only one to take a value and it does not expect to be passed a closure, as it will create the leaf elements in the tree structure.
[code]
def current
def root (Closure closure) {
def tree = [:]
def root = [:]
tree["root"] = root
def parent = current
current = root
closure.call()
current = parent
return tree
}
def node (key, Closure closure) {
def node = [:]
current[key] = node
def parent = current
current = node
closure.call()
current = parent
}
def leaf (key, value ) {
current[key] = value
}
// pseudo builder code
def tree = root {
node ("sub-tree-1") {
leaf "leaf-1", "leaf object 1"
}
node ("sub-tree-2"){
node ("node-1"){
leaf "leaf-2", "leaf object 2"
}
}
}
assert tree == [
root: [
"sub-tree-1": [
"leaf-1": "leaf object 1"
],
"sub-tree-2": [
"node-1": [
"leaf-2": "leaf object 2"
]
]
]
]
[/code]

Pretended methods


Many Groovy builders rely on the ability to describe arbitrarily-named elements. When we make use of markup builders to generate XML, we need to be able to insert whatever tag names are required to conform to the schema that we are using. Given that elements are created in method calls, we also need to be able to make arbitrarily- named method calls during the markup process. With Groovy, we can respond to methods that don’t exist as concrete methods of a class. The term we use for this type of methods is pretended methods. Groovy provides two means for implementing a pretended method.

invokeMethod


The PoorMansTagBuilder class that we covered in Chapter 5 uses invokeMethod as a means of pretending methods. The Poo rMansTagBuilder class works by handling all method calls to the builder, and invoking the closure argument manually. With invokeMethod, we can respond appropriately to any arbitrary method call. In this case, we output the appropriate XML tags.
[code lang=”java”]
class PoorMansTagBuilder {
int indent = 0
Object invokeMethod(String name, Object args) {
indent.times {print " "}
println "<${name}>"
indent++
args[0].delegate = this // Change delegate to the builder
args[0].call()
indent–
indent.times {print " "}
println "</${name}>"
}
}
[/code]
This is a simple case that we are using just to illustrate the mechanism. Although the technique works for simple cases, extending it to implement a more complete tag builder would rapidly result in complex and hard-to-maintain code.

methodMissing


Since Groovy 1.5, an alternative to invokeMethod was provided. The methodMissing mechanism differs slightly from invokeMethod, as it is only called when a method call fails to be dispatched to any concrete method. To update the PoorMansTagBuilder for using methodMissing instead of invokeMethod, all we need to do is replace the method name that we declare.
[code lang=”java”]
class PoorMansTagBuilder {
int indent = 0
def methodMissing(String name, args) {
indent.times {print " "}
println "<${name}>"
indent++
args[0].delegate = this // Change delegate to the builder
args[0].call()
indent–
indent.times {print " "}
println "</${name}>"
}
}
def builder = new PoorMansTagBuilder ()
builder.root {
level1{
level2 {
}
}
}
[/code]

Closure delegate


Earlier, we looked at how to code a pseudo builder using, methods declared within a script. The resolve strategy in that example passed method calls in the nested closure up to the owner of the closure. The builder block in the previous example is also in the scope of a script. Let’s decorate it as we did before, to identify the various anonymous closure instances.
[code lang=”java”]
// method root() called on PoorMansTagBuilder
builder.root { // Closure1
// method level1 called on Closure1 instance
level1{ // Closure2
// method level2 called on Closure2 instance
level2 { // Closure3
}
}
}
[/code]
The first method call to root() is made against the builder instance, so it will be handled directly by Poo rMansTagBuilder.methodMissing(). Nested method calls will first be dispatched to the enclosing closure. The lev el1() and lev el2() methods won’t be found in the closure instances, so we would normally expect the resolve strategy to dispatch these methods up the chain of owners until a method is found. This normal dispatch chain would end up at the script instance, so these methods would cause a MethodMissingException to be thrown. The secret of how this works is in the handling of the delegate for closure instances. The builder block starts with a direct method call onto the builder instance, builder. root(). Anonymous closure, Closure1, is passed as a par ameter. The call to root() will fail and fall through to methodMissing. In this simple example, arg[0] is always the closure because we are not processing parameters on our tags. A more sophisticated version would need to scan the parameters for the closure instance. At this point we have access to the closure, so we can set its delegate to the builder instance. Now when the level1() and level2() calls are encountered, the resolve strategy will try the owner first and then try the delegate as follows:

  • The level1() call will not be resolved in Closure1. It won’t be found in the owner of Closure1, which is the script, but it will be resolved in the delegate,which is the builder instance. PoorMansTagBuilder. methodMissing will field the method and also set the delegate for the anonymous closure, Closure2.

  • The level2() call ha ppens in the scope of Closure2 but will not be resolved there. First its owner, Closure1, will be tried, and then its delegate, which once again is the builder instance.

BuilderSupport

Under the hood, all of Groovy‘s own Builders are implemented by using the invokeMethod or methodMissing and delegate techniques that we have described above. We could choose to start creating our own builder classes by using these features alone. Perhaps the biggest challenge when creating a builder with these features alone is that the MOP concepts of pretended methods and delegate handling don’t fit well with the task at hand—namely the construction of complex objects. It would be nice to have APIs that refl ected the task at hand in a better way. Thankfully, the complexities of managing invokeMethod or methodMissing calls and figuring out who the delegate should be are encapsulated into the builder support classes provided in the Groovy packages. The most basic support class is Groovy.util.BuilderSupport.

BuilderSupport hook methods


BuilderSupport provides an interface to the building process that nicely mirrors the node-based construction process on which most builder classes are based. Instead of overriding invokeMethod as in the initial example, we override the node construction methods provided by BuilderSupport. These methods provide the hooks such that instead of coding at the MOP level with pretended method invocations and delegates, we can code with respect to the node construction process. The important hook methods that we need to know about are listed here. These methods encapsulate the building process out into node creation style events that make far more sense from an object construction point of view. Then we never need to worry about pretended methods or delegates again.

  • createNode(Object name)

  • createNode(Object name, Object value)

  • createNode(Object name, Map attributes)

  • createNode(Object name, Map attributes, Objects value)

    Called by BuilderSupport whenever a pretended method is encountered. The name parameter contains the name of the pretended call. The responsibility of the hook is to return a new object of a type appropriate to the method call. The specific hook to be called depends on what parameters are passed to the method.

  • nodeCompleted(Object parent, Object node)
    Called after all of the children of a node have been created.

  • setParent(Object parent, Object child)
    Called after createNode for each child node, in order to allow any parentchild
    relationships to be established.

BuilderSupport takes care of all of the nitty-gritty of handling pretended methods for us. Had our PoorMansTagBuilder worked only for parameter-less tags, BuilderSupport would have detected which type of call is being made and called the appropriate createNode for us. The setParent method is only called if a parent node exists.

How this all hangs together is best illustrated by way of an example. So let’s start by creating a really dumb builder that just logs these methods as they are encountered. This will give us a feel for the sequence in which the methods are called.
[code lang=”java”]
class LogBuilder extends BuilderSupport {
def indent = 0
def createNode(name){
indent.times {print " "}
println "createNode(${name})"
indent++
return name
}
def createNode(name, value){
indent.times {print " "}
println "createNode(${name}, ${value})"
indent++
return name
}
def createNode(name, Map attributes){
indent.times {print " "}
println "createNode(${name}, ${attributes})"
indent++
return name
}
def createNode(name, Map attributes, value){
indent.times {print " "}
println "createNode(${name}, ${attributes}, ${value})"
indent++
return name
}
void setParent(parent, child){
indent.times {print " "}
println "setParent(${parent}, ${child})"
}
void nodeCompleted(parent, node) {
indent–
indent.times {print " "}
println "nodeCompleted(${parent}, ${node})"
}
}
[/code]
To use this builder, all that we need to do is to construct one and start writing some markup with it. Here we have some markup for building customer records, but as this builder does not care what the method tags are, we could write whatever markup we please.
[code lang=”java”]
def builder = new LogBuilder()
def customers = builder.customers {
customer{
id(1001)
name(firstName:"Fred",surname:"Flintstone")
address("billing", street:"1 Rock Road",city:"Bedrock")
address("shipping", street:"1 Rock Road",city:"Bedrock")
}
}
[/code]
If we run this script, we will generate the following output. We can see from the output exactly what the sequence of calling is, and what parameters are being passed. We’ve used this simple example for illustrating how the BuilderSupport class works, but it is actually a useful debugging tool in general for using with any builder that’s not behaving as expected. By replacing any existing builder instance in your code with a LogBuilder, it will output the construction sequence for you, which may identify the problem.
[code lang=”java”]
createNode(customers)
createNode(customer)
setParent(customers, customer)
createNode(id, 1001)
setParent(customer, id)
nodeCompleted(customer, id)
createNode(name, [firstName:Fred, surname:Flintstone])
setParent(customer, name)
nodeCompleted(customer, name)
createNode(address, [street:1 Rock Road, city:Bedrock], billing)
setParent(customer, address)
nodeCompleted(customer, address)
createNode(address, [street:1 Rock Road, city:Bedrock], shipping)
setParent(customer, address)
nodeCompleted(customer, address)
nodeCompleted(customers, customer)
nodeCompleted(null, customers)
[/code]
From this output, we can trace the sequence in which the hooks are called. Nodes are created from the top down. The createNode hook for the parent is called first. The createNode hook for a child is called next, and setParent is called for each individual child after both the parent and the child have been created. The nodeCompleted hook is called only after all of the children have been created and their parent-child relations set. The default implementation of BuilderSupport manages the current node cursor by itself. Two additional hooks to consider are:


  • setCurrent(Object current)

  • Object getCurrent()


Certain builder implementations might want to manage the notion of a “current” node object in order to maintain a cursor on the construction process. If so, both of these hooks will need to be implemented. Now that we understand the building mechanism, it is a trivial matter to change our LogBuilder script to create some actual markup. Here, with a few modifications, we can turn our script into PoorMansTagBuilder 2.0.
[code lang=”java”]
class PoorMansTagBuilder20 extends BuilderSupport {
def indent = 0
def createNode(name){
indent.times {print " "}
println "<${name}>"
indent++
return name
}
def createNode(name, value){
indent.times {print " "}
println "<${name}>" + value
indent++
return name
}
def createNode(name, Map attributes){
indent.times {print " "}
print "<${name} "
print attributes.collect {
"${it.key}=’${it.value}’"
}.join(‘ ‘)
println ">"
indent++
return name
}
def createNode(name, Map attributes, value){
indent.times {print " "}
print "<${name} "
print attributes.collect {
"${it.key}=’${it.value}’"
}.join(‘ ‘)
println ">" + value
indent++
return name
}
void setParent(parent, child){
// Don’t care since we are just streaming to output
}
void nodeCompleted(parent, node) {
indent–
indent.times {print " "}
println "</${node}>"
}
}
[/code]
Once again, this is a simple implementation of a tag builder. We are making no interpretation of the method tags that are being passed in, so for each createNode call all we do is output a with parameters and attributes if necessary. The setParent call is not relevant to us because we are just streaming output to standard out. We will see in the next example where we need to implement this. Finally, the nodeCompleted call just closes the tag . Now we can apply this builder to the same customers markup script that we did before, as follows. The only change required is to instantiate a PoorMansTageBuilder20 in place of the original builder class.
[code lang=”java”]
def builder = new PoorMansTagBuilder20()
def customers = builder.customers {
customer {
id(1001)
name(firstName:"Fred",surname:"Flintstone")
address("billing", street:"1 Rock Road",city:"Bedrock")
address("shipping", street:"1 Rock Road",city:"Bedrock")
}
}
[/code]
Running this script will log some reasonably well-formed XML as follows:
[code lang=”xml”]
<customers>
<customer>
<id>1001
</id>
<name firstName=’Fred’ surname=’Flintstone’ >
</name>
<address street=’1 Rock Road’ city=’Bedrock’ >billing
</address>
<address street=’1 Rock Road’ city=’Bedrock’ >shipping
</address>
</customer>
</customers>
[/code]
As a markup builder, this falls well short of the features in the Groovy MarkupBuilder, but it does show just how easy it is to put together a quick builder to fit the need of the day. Now let’s consider what we’ve learned, and look at building something a little more useful.

A database builder


Every application that includes a database needs some means of setting up seed, demo, or test data. ihave worked on numerous enterprise applications during my career and invariably the management of different data sets becomes as much of an effort over time as the development of the application itself. In my own experience of working with Independent Software Vendors (ISVs), whose applications need to be deployed on multiple customer sites with multiple versions, the problem becomes acute. ISV companies often have competing needs for data sets. The sales organization needs a predictable data set for its demos to customers. The test department needs data sets that allow them to test specific features of the application. Project management requires specific seed data to be available, which is tailored to each
customer site prior to installation. With all of these competing requirements, the IT department has a limited set of database instances available on which to install and test all of these configurations.
There are various ways of managing data sets. The most common is to maintain SQL scripts that take care of the database insertions. Building a simple database will require multiple insertions into a multitude of tables. The SQL script needs to be written in such a way as to maintain the integrity of foreign key references. It’s not an easy thing to do, and requires intimate knowledge of the schema. Suppose we are working with a Grails application. Take for example the one-tomany relationship we looked at in Chapter 6:
[code lang=”java”]
class Customer {
String firstName
String lastName
static hasMany = [invoices:Invoice]
}
class Invoice {
static hasMany = [orders:SalesOrder]
}
class SalesOrder {
String sku
int amount
Double price
static belongsTo = Invoice
}
[/code]
Grails has a migration plug-in that can be installed. The migration tool will execute a SQL update script to migrate our database between versions. To use the migrate tool to add some simple test data for the above classes, we need to know how GORM maps from the Groovy POGO objects to relational tables. In Chapter 6, we also saw how these classes in fact map to five tables in the relational database. There are three main tables that represent the business objects (customer, invoice, and sales_order) and there are two mapping tables used to manage the foreign key mappings (customer_invoice and invoice_sales_order) that relate customers to invoices and invoices to sales orders.
To set up a simple test case with one customer, one invoice and three sales orders would require nine insertions across these tables. Apart from being error prone and difficult to maintain, the script will be incomprehensible to anyone who is not intimately acquainted with SQL. What starts out as a simple data input spec for a test case becomes a development task for a domain SQL expert who understands the
GORM mapping model. An alternative to this approach is to use the GORM APIs to build the test data. At least if we do this then we don’t have to concern ourselves with the foreign key relationships between tables. The script below will set up our simple data set with one customer, one invoice, and three sales orders:
[code]
def fred = new Customer(firstName:"Fred", lastName:"Flintstone")
fred.save()
def invoice = new Invoice()
invoice.addToOrders(new SalesOrder(sku:"productid01", amount:1,
price:1.00))
invoice.addToOrders(new SalesOrder(sku:"productid02", amount:3,
price:1.50))
invoice.addToOrders(new SalesOrder(sku:"productid03", amount:2,
price:5.00))
fred.addToInvoices(invoice)
[/code]
This is somewhat better than the SQL script approach, but it does impose a procedural construction onto the data, where the test data is typically defined declaratively. While I’ve used GORM to illustrate my point here, the same issues will crop up whatever persistence mechanism we use.
Ideally, we want to be able to describe our data in a declarative style. The syntax of the data definition should as closely match the structure of the resulting data as possible. This is an ideal situation in which to use a builder to take care of construction. With a
builder, it should be possible to create a declarative markup style script for building data sets. The builder can take care of the complexities of construction. Let’s first of all imagine how a builder for customers may look in use. We probably want to handle multiple customers, so a top-level customers method is useful. We could have multiple customer blocks nested below that. Nesting is a good way of
depicting ownership in a one-to-many relationship, so our Customers markup would probably look something like the following:
[code lang=”java”]
builder.customers {
customer{
invoice {
salesOrder()
salesOrder()
salesOrder()
}
}
}
[/code]
We need to be able to set the fields of each entity as it is created. We could have a pretended method for each field as follows:
[code lang=”java”]
builder.customers {
customer {
firstName("Fred")
lastName("Flintstone")
invoice {
salesOrder {
sku("productid01")
amount(1)
price(1.00)
}
salesOrder {
sku("productid02")
amount(2)
price(1.00)
}
salesOrder {
sku("productid03")
amount(3)
price(1.00)
}
}
}
}
[/code]
This will work. However, it is not immediately clear to a reader of this script that lastName is an object attribute and invoice is a new subsidiary object. A better option is to set object attributes as mapped parameter values. The following script is far clearer in its intent, so this is the one we will try to implement:
[code lang=”java”]
builder.customers {
customer(firstName:"Fred",lastName:"Flintstone") {
invoice {
salesOrder(sku:"productid01", amount:1, price:1.00)
salesOrder(sku:"productid02", amount:2, price:1.00)
salesOrder(sku:"productid03", amount:3, price:1.00)
}
}
}
[/code]
As it happens, the BuilderSupport hook methods and their calling sequence work perfectly in step with the GORM APIs that we need in order to construct our customer records.

  • The createNode method will be called in the correct top down sequence, allowing us to create the appropriate Customer, Invoice, or SalesOrder as required.

  • The setParent hook is called after both parent and child objects have been constructed, allowing us to call Customer.addToInvoices or
    Invoice.addToOrders when we need to.

  • The nodeCompleted hook can be used to intercept when an object needs to be saved.


The following code snippet contains a rudimentary builder class based on BuilderSupport that constructs customer, invoice, and sales order objects through GORM. The same style of builder could work equally well with whatever other persistence method we choose.
[code lang=”java”]
class CustomersBuilder extends BuilderSupport {
def createNode(name){
Object result = null
switch (name) {
case "customer":
return new Customer(firstName:"", lastName:"")
case "invoice":
return new Invoice()
case "salesOrder":
return new SalesOrder(sku:"default",amount:1,price:0.0)
}
}
def createNode(name, value){
Object result = createNode(name)
if (value instanceof Customer && result instanceof Invoice)
value.addToInvoices(result)
if(value instanceof Invoice && result instanceof SalesOrder)
value.addToOrders(result)
return result
}
def createNode(name, Map attributes){
Object result = null
switch (name) {
case "customer":
return new Customer(attributes)
case "invoice":
return new Invoice(attributes)
case "salesOrder":
return new SalesOrder(attributes)
}
}
def createNode(name, Map attributes, value){
Object result = createNode(name,attributes)
if (value instanceof Customer && result instanceof Invoice)
value.addToInvoices(result)
if(value instanceof Invoice && result instanceof SalesOrder)
value.addToOrders(result)
return result
}
void setParent(parent, child){
if (child instanceof Invoice && parent instanceof Customer)
parent.addToInvoices(child)
if (child instanceof SalesOrder && parent instanceof Invoice)
parent.addToOrders(child)
}
void nodeCompleted(parent, node) {
if (node != null)
node.save()
}
}
[/code]
Here we have implemented all four createNode methods. The method tag is passed as the name parameter to createNode. So we construct a Customer, Invoice, or SalesOrder object based on the tag that we are processing. We allow a parent object to be set in the value parameter to the method. This allows us to construct a child object outside the scope of a parent, and set its parent later. The setParent method takes care of adding invoices to customers and sales orders to invoices. Testing the instanceof both parent and child ensures that we don’t
attempt to add an invoice if it is declared outside of the customer. All that remains for nodeCompleted to do is to save the node object that we have created to the database. When we put all of this together, we can make use of our CustomerBuilder to build a simple test database as follows:
[code lang=”java”]
def builder = new CustomersBuilder()
def customers = builder.customers {
fred = customer(firstName:"Fred",lastName:"Flintstone") {
invoice {
salesOrder(sku:"productid01", amount:1, price:1.00)
salesOrder(sku:"productid02", amount:2, price:1.00)
salesOrder(sku:"productid03", amount:3, price:1.00)
}
}
invoice2 = invoice(fred)
salesOrder(invoice2, sku:"productid04", amount:1, price:1.00)
salesOrder(invoice2, sku:"productid05", amount:1, price:1.00)
salesOrder(invoice2, sku:"productid06", amount:1, price:1.00)
}
[/code]
By allowing a parent object to be passed as the value parameter, we have made the markup script more fl exible. As you can see from the preceding code, invoice and salesOrder tags can be declared directly as children of a parent object, or they can be declared independently. This gives us a bit more fl exibility in what types of mapping relationships we can support where ownership between parent and child
might be optional, or in more complex scenarios where many-to-many relationships might need to be declared.

FactoryBuilderSupport

BuilderSupport is the base class for many of the builder classes provided in the Groovy packages. As we can see from the previous examples, it is easy to work with. We have built quite a useful database builder tool in relatively few lines of code. However, one issue with BuilderSupport is that the hook functions are in effect funnels for handling all of the possible tags that we might like to process in our markup. In our CustomerBuilder we are handling just four different tags. This is not a realistic scenario for most database schemas. We could expect to have dozens more tag types that we need to handle if we wanted to expand this example into something that would work with a typical database schema for even a modestly sized application. Funneling all of these tags into one createNode would create an unwieldy mess of code.

[code lang=”java”]
def createNode(name){
Object result = null
switch (name) {
case "customer":
return new Customer(firstName:"", lastName:"")
case "invoice":
return new Invoice()
case "sales_order":
return new SalesOrder(sku:"default",amount:1,price:0.0)
case "another_object":
return new Something()
…….. and more!
}
}
[/code]
Groovy provides a second builder support class that neatly overcomes this problem. The Groovy.util.FactoryBuilderSupport class is based on the factory pattern, and delegates the handling of individual tag objects to Factory classes. Originally, this support class was just provided as part of the SwingBuilder. Because it was clear that this was more generally useful, the code was then refactored to be generally usable as a standalone Builder class. Since then, it has become the basis for other builders, such as the recently-added JmxBuilder, and is available to us for deriving our own factory-based builders.
FactoryBuilderSupport works by orchestrating the construction process in concert with Factory classes. When the FactoryBuilderSupport class encounters a method tag, it constructs an appropriate Factory object to handle it. The factory provides method hooks that implement the construction of the individual object and the setting up of parent-child relationships between the objects. To implement a builder with the FactoryBuilderSupport class, we must first declare a Factory class for each object type that we wish to process. Factory classes are derived from the Groovy.util.AbstractFactory class and need to overload some or all of the following methods from the AbstractFactory class:


  • newInstance

  • Called by FactoryBuilderSupport whenever it wants an object of a particular type to be constructed. It is similar to the createNode methods of BuilderSupport except that there is just one newInstance method, which accepts all argument types regardless of whether a value or attributes are supplied or not.
  • onHandleNodeAttributes

  • Allows the Factory class to take over the management of attributes. It can stop the builder from processing attributes by returning true.
  • setParent and setChild

  • Provide hooks for managing the parent-child relationships between objects.
  • isLeaf

  • We set this method to return true if the method tag being handled should be a leaf node and stops the builder treating any subsequent method calls as object declarations.
  • onNodeCompleted

  • Called when a node is completed, in order to allow any finalization of the object to be performed. It is similar to nodeCompleted in BuilderSupport.

To build a replacement for the CustomerBuilder with FactoryBuilderSupport, we first need to define Factory classes for each of the tag methods that we need to process. The first of these is the customers tag, which is straightforward enough. This tag does not cause any objects to be created, so all we do is return the tag name as the object created.
[code lang=”java”]
public class CustomersFactory extends AbstractFactory {
public boolean isLeaf() {
return false
}
public Object newInstance(FactoryBuilderSupport builder,
Object name, Object value, Map attributes
) throws InstantiationException, IllegalAccessException {
return name
}
}
[/code]
We then define a factory class for the customer object. The methods that we need to implement are isLeaf (returns false), newInstance (to create the customer object), and onNodeCompleted (to save it).
[code lang=”java”]
public class CustomerFactory extends AbstractFactory {
public boolean isLeaf() {
return false
}
public Object newInstance(FactoryBuilderSupport builder,
Object name, Object value, Map attributes
) throws InstantiationException, IllegalAccessException {
Customer customer = null
if (attributes != null)
customer = new Customer(attributes)
else
customer = new Customer()
return customer
}
public void onNodeCompleted(FactoryBuilderSupport builder,
Object parent, Object customer) {
customer.save()
}
}
[/code]
The factory for invoices is equally straightforward. The only addition is that we need to take care of the parent-child relationship between customer and invoice. We do this by adding a setParent method, which will call addToInvoices on the customer object if required. We also need to check the value parameter passed to newInstance to see if a parent is being set at this point.
[code lang=”java”]
public class InvoiceFactory extends AbstractFactory {
public boolean isLeaf() {
return false
}
public Object newInstance(FactoryBuilderSupport builder,
Object name, Object value, Map attributes
) throws InstantiationException, IllegalAccessException {
Invoice invoice = null
if (attributes != null)
invoice = new Invoice(attributes)
else
invoice = new Invoice()
if (value != null && value instanceof Customer)
value.addToInvoices(invoice)
return invoice
}
public void setParent(FactoryBuilderSupport builder,
Object parent, Object invoice) {
if (parent != null && parent instanceof Customer)
parent.addToInvoices(invoice)
}
public void onNodeCompleted(FactoryBuilderSupport builder,
Object parent, Object invoice) {
invoice.save()
}
}
[/code]
The factory for sales orders is identical to invoices except that we now return true from isLeaf because a sales order object will always be a leaf node in our tree.
[code lang=”java”]
public class SalesOrderFactory extends AbstractFactory {
public boolean isLeaf() {
return true
}
public Object newInstance(FactoryBuilderSupport builder,
Object name, Object value, Map attributes
) throws InstantiationException, IllegalAccessException {
SalesOrder sales_order = null
if (attributes != null)
sales_order = new SalesOrder(attributes)
else
sales_order = new SalesOrder()
if (value != null && value instanceof Invoice)
value.addToOrders(sales_order)
return sales_order
}
public void setParent(FactoryBuilderSupport builder,
Object parent, Object sales_order) {
if (parent != null && parent instanceof Invoice)
parent.addToOrders(sales_order)
}
public void onNodeCompleted(FactoryBuilderSupport builder,
Object parent, Object sales_order) {
sales_order.save()
}
}
[/code]
All of the intelligence of how to orchestrate the construction process is encapsulated in the FactoryBuilderSupport class. So literally all we need to do for the whole builder to work is to register the Factory classes with appropriate tag names.
[code lang=”java”]
public class CustomersFactoryBuilder extends FactoryBuilderSupport {
public CustomersFactoryBuilder(boolean init = true) {
super(init)
}
def registerObjectFactories() {
registerFactory("customers", new CustomersFactory())
registerFactory("customer", new CustomerFactory())
registerFactory("invoice", new InvoiceFactory())
registerFactory("sales_order", new SalesOrderFactory())
}
}
[/code]
FactoryBuilderSupport uses refl ection at runtime to detect what registration methods to run. By scanning the list of methods in the MetaClass instance and looking for methods that begin with “register”, FactoryBuilderSupport detects whether any additional registration methods are provided in the derived builder class. In the preceding example, the only registration method added is registerObjectFactories, but we could well have written:
[code lang=”java”]
def registerCustomers() {
registerFactory("customers", new CustomersFactory())
}
def registerCustomer() {
registerFactory("customer", new CustomerFactory())
}
def registerInvoice() {
registerFactory("invoice", new InvoiceFactory())
}
def registerSalesOrder() {
registerFactory("sales_order", new SalesOrderFactory())
}
[/code]
FactoryBuilderSupport would detect all of these and run them in turn. Which method you use is a matter of choice. The only issue that you need to be aware of is that the registration methods will not be called in any predetermined order. If there are dependencies in your registration code, then it’s best to group these into a single registration method.
To finish, we can drop this modified builder right where we previously used CustomersBuilder, and it will work in the same way.
[code lang=”java”]
def builder = new CustomersFactoryBuilder()
def customers = builder.customers {
fred = customer(firstName:"Fred",lastName:"Flintstone") {
invoice {
salesOrder(sku:"productid01", amount:1, price:1.00)
salesOrder(sku:"productid02", amount:2, price:1.00)
salesOrder(sku:"productid03", amount:3, price:1.00)
}
}
invoice2 = invoice(fred)
salesOrder(invoice2, sku:"productid04", amount:1, price:1.00)
salesOrder(invoice2, sku:"productid05", amount:1, price:1.00)
salesOrder(invoice2, sku:"productid06", amount:1, price:1.00)
}
[/code]
In terms of management and maintenance, this version is far superior. Adding capabilities now for new tables will simply involve writing a new Factory class and registering it.

Summary

In Chapter 5, we discussed how builders worked via the Groovy MOP. In this chapter, we have taken a deeper look at how features of the MOP are used to implement the builder pattern. We’ve looked at the language features used to create a builder, and seen how they involve implementing pretended methods and infl uencing how methods calls are resolved. Implementing a builder directly by using the MOP in this way focuses on the nuts and bolts of the semantics of the builder, rather than the construction process.
In this chapter, we have seen how Groovy provides two useful support classes that make it much simpler to implement our own builders than if we use the MOP. We’ve seen how to use BuilderSupport and FactoryBuilderSupport to create our own builder classes. Using these support classes greatly simplifies the implementation of builders. Hopefully, this will inspire you to see opportunities to develop your own Groovybased builders for you own applications. You can find the full documentation for all of the classes that we covered here on the Codehaus website. The Groovy document for the classes can be found at http://Groovy.codehaus.org/api/Groovy/util/
package-summary.html.

also read:

  • Groovy Tutorials
  • Creating JSON using Groovy
  • Developing Groovy based web application and deploying to Google App Engine

Filed Under: Groovy Tagged With: Groovy Basics

Designing and Developing Secure Java EE Applications using GlassFish Security

October 6, 2010 by itadmin Leave a Comment

GlassFish Security

We are living in a world full of dazzling wonders, and ifor one always enjoy encountering them. Software development is one of the wonders that dazzles me because of its enormously vast domain, including many concerns and subjects of interest. Looking at this domain from any distance, we will see one big and sometimes blurry-edged spot named security.
Security, an orthogonal and inseparable part of software systems, is not for preventing others from accessing some information and system resources but for allowing them access in an appropriate way, by implementing necessary means to precisely check any attempt to access a resource and either allow it to go further or not and record all information related to examining this attempt for further review.

also read:

  • Java EE Tutorials
  • Java EE 7 Tutorials
  • Java EE Interview Questions

Java EE is the platform of choice for developing enormously large-scale applications, and provides plethora of features for implementing security plans for applications, starting from dealing with identity storage and identity solutions up to providing GUI-level support for security concerns and integration with other security providers.

Nowadays, integration is something that we hear in every software development meeting and session independent from what the session is about. Security integration, however, is
a delicate matter compared to all other issues as it deals directly with the organization’s assets. Java EE design allows it to delegate its security requirements to another entity in the enterprise, like a single sign-on solution, which on the other hand can integrate with
other products and platforms in use in the organization. The GlassFish Security book is an attempt to explain this domain considering Java EE, GlassFish, and OpenSSO capabilities and features.

What This Book Covers

Chapter 1, Java EE Security Model, discusses how we can secure different Java applications by using the declarative security model or by using the APiexposed by Java EE containers to access the security enforcement layers programmatically. It also briefly introduces Web modules, EJB modules, and application client module’s security in different levels, including authentication, authorization, and transport security.
Chapter 2, GlassFish Security Realms, discusses JAAS and GlassFish security realm, including File realm, JDBC realm, LDAP realm, and Certificate realm in detail as that will be required to develop a secure enterprise application. It also discusses GlassFish application server interaction with identity storages such as relational databases, Lightweight Directory Access Protocol (LDAP) servers, fl at file storage, and so on.
Chapter 3, Designing and Developing Secure Java EE Applications, covers developing and deploying a secure Java EE application with all standard modules including Web, EJB, and application client modules. It also teaches us how we can secure EJBs using annotation and then use a web frontend to use the secured EJBs after a user provides correct identification information.
Chapter 4, Securing GlassFish Environment, helps you secure your operating system and environment from unprivileged access by applications deployed in GlassFish using the OS features and Java policy management. It also covers network communication security, GlassFish password security, and finally security auditing, which is a complementary function in software security.
Chapter 5, Securing GlassFish, covers GlassFish administration security tasks such as password security and listener security. This chapter will teach you to secure GlassFish by examining the administration security, password protection, and network listener security. It also discusses the benefits of virtual servers for isolating different applications deployed in a single machine with a single IP address.
Chapter 6, Introducing OpenDS: Open Source Directory Service, teaches you about directory service and the set of features OpenDS provides—installing, administrating, and monitoring OpenDS and using OpenDS in embedded mode. This chapter teaches you to set up a replication topology to ensure service and data availability in case of unpredicted disasters.
Chapter 7, OpenSSO, the Single sign-on Solution, covers projects security from an integration point of view. In this chapter you will install and configure OpenSSO and understand different methods of using OpenSSO. It also teaches you how to use OpenSSO RESTful Web Services for authentication, authorization, and acquiring SSO tokens.
Chapter 8, Securing Java EE Applications using OpenSSO, covers OpenSSO Policy Agents that let us as architects, system designers, and developers secure a Java EE application using OpenSSO without changing the application source code. It also discusses about Policy Agents, Policy Agent’s installation, and administration, along with changing our sample application to place it under agent protection instead of using plain Java EE protection.
Chapter 9, Securing Web Services by OpenSSO, covers Web Services security and how we can use OpenSSO and OpenSSO agents to secure our Web Services deployed in GlassFish. It also teaches you to install OpenSSO Web Services Security Provider Agent and develop a simple, secure pair of WSP and WSC.

Designing and Developing Secure Java EE Applications

In previous chapters we discussed how we can utilize Java EE capabilities to secure our Java EE applications. In this chapter, we are going to put what we learned into practice and develop a secure Java EE application with all standard modules including Web, EJB, and application client modules. Security is an orthogonal concern for an application and we should assess it right from the start by reviewing the analysis we receive from business and functional analysts. Assessing the security requirements results in understanding the functionalities we need to include in our architecture to deliver a secure application covering the necessary requirements.

Security necessities can include a wide area of requirements, which may vary from a simple authentication to several sub-systems. A list of these sub-systems includes identity and access management system and transport security, which can include encrypting data as well.
In this chapter we will develop a secure Java EE application based on Java EE and GlassFish capabilities. In course of the chapter we will cover following topics:

  • Analyzing Java EE application security requirements
  • Including security requirements in Java EE application design
  • Developing secure Business layer using EJBs
  • Developing secure Presentation layer using JSP and Servlets
  • Configuring deployment descriptors of Java EE applications
  • Specifying security realm for enterprise applications
  • Developing secure application client module
  • Configuring Application Client Container

Understanding the sample application

The sample application that we are going to develop, converts different length measurement units into each other. Our application converts meter to centimeter, millimeter, and inch. The application also stores usage statistics for later use cases. Guest users who prefer not to log in can only use meter to centimeter conversion, while any company employee can use meter to centimeter and meter to millimeter conversion, and finally any of company’s managers can access meter to inch in addition to two other conversion functionalities. We should show a custom login page to comply with site-wide look and feel. No encryption is required for communication between clients and our application
but we need to make sure that no one can intercept and steal the username and passwords provided by members. All members’ identification information is stored in the company’s wide directory server. The following diagram shows the high-level functionality of the sample application:

We have login action and three conversion actions. Users can access some of them after logging in and some of them can be accessed without logging in.

Analyzing sample application business logic

Before looking at security requirements and factors affecting the software security let’s see what we need to provide in our business layer. Our business logic consists of conversion operations and persistence of the conversion operations usage statistics. We can use a stateless Session Bean with three methods, one for each type of conversion. And for statistics persistence we can use EJB 3 entity beans. After studying the application description we can extract the following security-related requirements which we need to address to comply with the application description:

  • Authentication is required
  • Authentication should happen over a secure channel
  • Authorization is required
  • We need to use LDAP security realm

So far we translated the business analysis to technical requirements and now we are going to check each requirement in further detail to extract the implementation details. For implementing the sample application we can use a simple bottom-up procedure.
The following diagram shows the application blocks down to JSP files, Servlet, and EJBs.

As you can see we have Web module, EJB module, and an application client module. The Web module and the application client module presents a frontend for the EJB layer that performs both business logic, which is the conversion operations, and storing the conversion operation invocation statistics using Entity Beans. GlassFish uses the LDAP realm to authenticate the users against the specified directory server.

Implementing the Business and Persistence layers

The Persistence layer consists of an Entity Bean named Visit; we use this entity bean to store information about each visit. We will use a session bean with three business methods to convert a given length in meter to centimeter, millimeter, and inch.

Implementing the Persistence layer

We are using EJB 3 to develop the Persistence layer so we will only need to implement the entity bean and define the persistence unit. The following listing shows the Visit class.

[code lang=”java”]
Complete code for this class is available in the book’s source code:
https://www.packtpub.com//sites/default/files/
downloads/9386_Code.zip.

@Entity
public class Visit implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Temporal(javax.persistence.TemporalType.DATE)
private Date visitDate;
private String username;
private String operationName;
private int conversionValue;
public Visit() {
}
public Visit(Date visitDate, String username, String Operation,
int conversionValue) {
this.visitDate = visitDate;
this.username = username;
this.operationName = Operation;
this.conversionValue = conversionValue;
}
}
[/code]

Now that our entity bean is ready we can start looking at our session bean that drives the application business logic and also stores information about each invocation using the Visit entity bean. The following listing shows Conversion session bean local interface.

[code lang=”java”]
@ Local
public interface ConversionLocal {
float toInch(int meter);
int toCentimeter(int meter);
int toMillimeter(int meter);
}
[/code]

All of these methods are implemented in Conversion bean implementation which is as follows:

[code lang=”java”]
@ Stateless
public class ConversionBean implements ConversionLocal {
@PersistenceContext(unitName = "chapter3")
private EntityManager em;
@Resource
private SessionContext ctx;
@RolesAllowed({"manager_role"})
public float toInch(int meter) {
persist(meter, "toInch");
return Math.round(meter * 39.37);
}
@PermitAll
public int toCentimeter(int meter) {
persist(meter, "toCentimeter");
return meter * 100;
}
@RolesAllowed("employee_role")
public int toMillimeter(int meter) {
persist(meter, "toInch");
return meter * 1000;
}
private void persist(int value, String operationName) {
String userName = ctx.getCallerPrincipal().getName();
Visit v = new Visit(new Date(), userName, operationName,
value);
em.persist(v);
}
}
[/code]

Starting from the first line we are using @S tateless to mark this class as a stateless Session Bean. Later on we are using @P ersistenceContext to inject an entity manager into the instance. We will use this entity manager to store Visit entities. Then we are using @R esource to inject the current SessionContext into the session bean. Later on we will use it to extract the current principal and username of the invoker. The first security-related annotation is @R olesAllowed({“manager”}), which instructs the application server to only permit an authenticated user with
manager role to invoke this method. After this we have @P ermitAll which instructs the application server to allow anyone, either authenticated or not, to invoke this method. And finally we are using @R olesAllowed(“employee”) to instruct the application server that any authenticated user with employee role can invoke this method.

The persist method stores the invocation information. This information includes the current invoker username, which we extract from SessionContext using the getCallerPrincipal().getName() method. Finally we have a persistence unit that uses sample data source and sample
database which is bundled with GlassFish. The listing shown below contains a snippet of persistence.xml file, which configures a persistence unit for chapter3.

[code lang=”xml”]
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="chapter3" transaction-type="JTA">
<provider>oracle.toplink.essentials.PersistenceProvider
</provider>
<jta-data-source>jdbc/sample</jta-data-source>
<class>book.glassfish.security.chapter3.Visit</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="toplink.ddl-generation"
value="drop-and-create-tables"/>
</properties>
</persistence-unit>
</persistence>
[/code]

Now that we have our Persistence and Business layers ready we can start looking at the Web layer and how the Web layer can complement the inner layer in securing the system.

Developing the Presentation layer

The Presentation layer is the closest layer to end users when we are developing applications that are meant to be used by humans instead of other applications. In our application, the Presentation layer is a Java EE web application consisting of the elements listed in the following table. In the table you can see that different JSP files are categorized into different directories to make the security description easier.

Now that our application building blocks are identified we can start implementing them to complete the application. Before anything else let’s implement JSP files that provides the conversion GUI. The directory layout and content of the Web module is shown in the following figure:

Implementing the Conversion GUI

In our application we have an index.jsp file that acts as a gateway to the entire system and is shown in the following listing:

[code lang=”html”]
<html>
<head><title>Select A conversion</title></head>
<body><h1>Select A conversion</h1>
<a href="auth/login.html">Login</a>
<br/>
<a href="jsp/toCenti.jsp">Convert Meter to Centimeter</a>
<br/>
<a href="jsp/toInch.jsp">Convert Meter to Inch</a>
<br/>
<a href="jsp/toMilli.jsp">Convert to Millimeter</a><br/>
<a href="auth/logout.jsp">Logout</a>
</body>
</html>

[/code]

Implementing the Converter servlet

The Converter servlet receives the conversion value and method from JSP files and calls the corresponding method of a session bean to perform the actual conversion. The following listing shows the Converter servlet content:
[code lang=”java”]
@WebServlet(name="Converter", urlPatterns={"/Converter"})
public class Converter extends HttpServlet {
@EJB
private ConversionLocal conversionBean;
protected void processRequest(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
}
@Override
protected void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
System.out.println("POST");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
try{
int valueToconvert =
Integer.parseInt(request.getParameter("meterValue"));
String method = request.getParameter("method");
out.print("<hr/> <center><h2>Conversion Result is: ");
if (method.equalsIgnoreCase("toMilli")) {
out.print(conversionBean.toMillimeter(valueToconvert));
} else if (method.equalsIgnoreCase("toCenti")) {
out.print(conversionBean.toCentimeter(valueToconvert));
} else if (method.equalsIgnoreCase("toInch")) {
out.print(conversionBean.toInch(valueToconvert));
}
out.print("</h2></center>");
}catch (AccessLocalException ale) {
response.sendError(401);
}finally {
out.close();
}
}
}
[/code]

Starting from the beginning we are using annotation to configure the servlet mapping and servlet name instead of using the deployment descriptor for it. Then we use dependency injection to inject an instance of Conversion session bean into the servlet and decide which one of its methods we should invoke based on the conversion type that the caller JSP sends as a parameter. Finally, we catch  javax.ejb.AccessLocalException and send an HTTP 401 error back to inform the client that it does not have the required privileges to perform the requested action. The following figure shows what the result of invocation could look like:

Each servlet needs some description elements in the deployment descriptor or included as deployment descriptor elements.  Implementing the conversion JSP files is the last step in implementing the functional pieces. In the following listing you can see content of the toMilli.jsp file.

[code lang=”html”]
Convert To Millimeter
<html>
<head><title>Convert To Millimeter</title></head>
<body><h1>Convert To Millimeter</h1>
<form method=POST action="../Converter">Enter Value to
Convert: <input name=meterValue>
<input type="hidden" name="method" value="toMilli">
<input type="submit" value="Submit" />
</form>
</body>
</html>

[/code]

The toCenti.jsp and toInch.jsp files look the same except for the descriptive content and the value of the hidden parameter which will be toCentiand toInch respectively for toCenti.jsp and toInch.jsp. Now we are finished with the functional parts of the Web layer; we just need to implement the required GUifor security measures.

Implementing the authentication frontend

For the authentication, we should use a custom login page to have a unified look and feel in the entire web frontend of our application. We can use a custom login page with the FORM authentication method. To implement the F ORM authentication method we need to implement a login page and an error page to redirect the users to that page in case authentication fails. Implementing authentication requires us to go
through the following steps:

  • Implementing login.html and loginError.html
  • Including security description in the web.xml and sun-web.xml or
    sun-application.xml

Implementing a login page

In FORM authentication we implement our own login form to collect username and pa ssword and we then pass them to the container for authentication. We should let the container know which field is username and which field is password by using standard names for these fields. The username field is j_ username and the password field is j_ password. To pass these fields to container for authentication we should use j_security_check as the form action. When we are posting to j_ security_check the servlet container takes action and authenticates the included j_username and j_password against the configured realm. The listing below shows login.html content.
[code lang=”html”]
<form method="POST" action="j_security_check">
Username: <input type="text" name="j_username"><br />
Password: <input type="password" name="j_password"><br />
<br />
<input type="submit" value="Login">
<input type="reset" value="Reset">
</form>

[/code]

The following figure shows the login page which is shown when an unauthenticated user tries to access a restricted resource:

Implementing a logout page

A user may need to log out of our system after they’re finished using it. So we need to implement a logout page. The following listing shows the logout.jsp file:
[code lang=”html”]
<%
session.invalidate();
%>
<body>
<center>
<h1>Logout</h1>
You have successfully logged out.
</center>
</body>

[/code]

Implementing a login error page

And now we should implement LoginError.html, an authentication error page to inform user about its authentication failure.
[code lang=”java”]

<html>
<body>
<h2>A Login Error Occurred</h2>
Please click <a href="login.html">here</a> for another try.
</body>
</html>

[/code]

Implementing an access restricted page

When an authenticated user with no required privileges tries to invoke a session bean method, the EJB container throws a javax.ejb.AccessLocalException. To show a meaningful error page to our users we should either map this exception to an error page or we should catch the exception, log the event for audition purposes, and then use the sen dError() method of the Htt pServletResponse object to send out an error code. We will map the HTTP error code to our custom web pages with meaningful descriptions using the web.xml deployment descriptor. You will see which configuration elements we will use to do the mapping. The following snippet shows AccessRestricted.html file:
[code lang=”html”]
<body>
<center> <p>You need to login to access the requested
resource. To login go to <a href="auth/login.html">Login
Page</a></p></center>
</body>
[/code]

Configuring deployment descriptors

So far we have implemented required files for the FORM-based authentication and we only need to include required descriptions in the web.xml file. L ooking back at the application requirement definitions, we see that anyone can use meter to centimeter conversion functionality and any other functionality that requires the user to login. We use three different HTML pages for different types of conversion. We do not need any constraint on toC entimeter.html therefore we do not need to include any definition for it. Per application description, any employee can access the toMilli.jsp page. Defining security constraint for this page is shown in the following listing:
[code lang=”html”]
<security-constraint>
<display-name>You should be an employee</display-name>
<web-resource-collection>
<web-resource-name>all</web-resource-name>
<description/>
<url-pattern>/jsp/toMillimeter.html</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
<http-method>DELETE</http-method>
</web-resource-collection>
<auth-constraint>
<description/>
<role-name>employee_role</role-name>
</auth-constraint>
</security-constraint>

[/code]

We should put enough constraints on the toInch.jsp page so that only managers can access the page. The listing included below shows the security constraint definition for this page.
[code lang=”xml”]

<security-constraint>
<display-name>You should be a manager</display-name>
<web-resource-collection>
<web-resource-name>Inch</web-resource-name>
<description/>
<url-pattern>/jsp/toInch.html</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<description/>
<role-name>manager_role</role-name>
</auth-constraint>
</security-constraint>

[/code]

Finally we need to define any role we used in the deployment descriptor. The following snippet shows how we define these roles in the web.xml page.
[code lang=”xml”]
<security-role>
<description/>
<role-name>manager_role</role-name>
</security-role>
<security-role>
<description/>
<role-name>employee_role</role-name>
</security-role>
[/code]

Looking back at the application requirements, we need to define data constraint and ensure that username and passwords provided by our users are safe during transmission. The following listing shows how we can define the data constraint on the login.html page.
[code lang=”xml”]
<security-constraint>
<display-name>Login page Protection</display-name>
<web-resource-collection>
<web-resource-name>Authentication</web-resource-name>
<description/>
<url-pattern>/auth/login.html</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<user-data-constraint>
<description/>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
[/code]

One more step and our web.xml file will be complete. In this step we define an error page for HTML 401 error code. This error code means that application server is unable to perform the requested action due to negative authorization result. The following snippet shows the required elements to define this error page.
[code lang=”xml”]
<error-page>
<error-code>401</error-code>
<location>AccessRestricted.html</location>
</error-page>
[/code]

Now that we are finished with declaring the security we can create the conversion pages and after creating these pages we can start with Business layer and its security requirements.

Specifying the security realm

Up to this point we have defined all the constraints that our application requires but we still need to follow one more step to complete the application’s security configuration. The last step is specifying the security realm and authentication. We should specify the FORM authentication and per-application description; authentication must happen against the company-wide LDAP server. Here we are going to use the LDAP security realm LDAPRealm which we created in Chapter 2. We need to import a new LDIF file into our LDAP server, which contains groups and users definition required for this chapter. To import the file we can use the following command, assuming that you downloaded the source code bundle from https://www.packtpub.com//sites/default/files/downloads/9386_Code.zip and you have it extracted.
[code lang=”java”]
import-ldif –ldifFile path/to/chapter03/users.ldif
–backendID userRoot –clearBackend –hostname 127.0.0.1 –port 4444 —
bindDN cn=gf\ cn=admin –bindPassword admin –trustAll –noPropertiesFile
[/code]

The following table show users and groups that are defined inside the users.ldif file.

We used OpenDS for the realm data storage and it had two users, one in the employee group and the other one in the manager group. To configure the authentication realm we need to include the following snippet in the web.xml file.

[code lang=”xml”]
<login-config>
<auth-method>FORM</auth-method>
<realm-name>LDAPRealm</realm-name>
<form-login-config>
<form-login-page>/auth/login.html</form-login-page>
<form-error-page>/auth/loginError.html</form-error-page>
</form-login-config>
</login-config>
[/code]

If we look at our Web and EJB modules as separate modules we must specify the role mappings for each module separately using the GlassFish deployment descriptors, which are sun-web.xml and sun-ejb.xml. But we are going to bundle our modules as an Enterprise Application Archive (EAR) file so we can use the GlassFish deployment descriptor for enterprise applications to define the role mapping in one place and let all modules use that definitions. The following listing shows roles and groups mapping in the sun-application.xml file.
[code lang=”xml”]
<sun-application>
<security-role-mapping>
<role-name>manager_role</role-name>
<group-name>manager</group-name>
</security-role-mapping>
<security-role-mapping>
<role-name>employee_role</role-name>
<group-name>employee</group-name>
</security-role-mapping>
<realm>LDAPRealm</realm>
</sun-application>

[/code]

The security-role-mapping element we used in sun-application.xml has the same schema as the security-role-mapping element of the sun-web.xml and sun-ejb-jar.xml files. You should have noticed that we have a realm element in addition to role mapping elements. We can use the realm element of the sun-application.xml to specify the default authentication realm for the entire application instead of specifying it for each module separately.

Deploying the application client module in the Application Client Container

The application client module can be a first layer Java SE application which directly communicates with the EJB container and uses services like transaction and security management of EJB container through the Application Client Container. When it comes to software structure an application client is not different from a simple Java SE application. It has a main method, which is the software entry point and we can access different Java EE services simply with annotation or using deployment descriptors. The following listing shows the main method for our application client, which invokes the Conversion Session Bean and prints the result.

[code lang=”java”]
public class Main {
@EJB
private static ConversionRemote conversionBean;
public static void main(String[] args) {
System.out.println(conversionBean.toInch(10));
}
}
[/code]

You may ask how this application can use injection and access an EJB instance. The secret is, as we saw in Chapter 1, hiding in another type of container called the Application Client Container. We deploy an application client module in the ACC and later execute it in the machine either as Java Web Start application or simply using GlassFish-provided scripts. When we run this application the following
procedure takes place:

  1. Application client (launched using Web Start or directly) results in the ACC trying to inject the secured EJB.
  2. The EJB method requires authentication, so GlassFish calls the default CallbackHandler to get user login.
  3. The default CallbackHandler, which is a simple username and password collecting dialog, appears on the client’s screen.
  4. The collected username and password are sent back to application server for authentication and authorization.
  5. After a successful authentication, the method invocation goes through.

This procedure happens even if we do not add any single line of configuration to our EJB module deployment descriptor or Application Client deployment descriptor. The following figure shows more detail about the interaction between different modules when a secure EJB is called from an application client.


The default configuration for application client authentication is summarized in the following table:

All of these measures are configurable either through the Application Client deployment descriptor or the EJB deployment descriptor or the ACC deployment descriptor. The following table shows which attributes are configurable through each one of these deployment descriptors.

Two of the deployment descriptors included in the above table are specific to each vendor and may differ between different application servers. The only standard descriptor is application-client.xml, which is a part of the application client standard. This descriptor is placed inside the META-INF directory of the client application and contains information like which resources our application is using,
how the application is accessing these resources, and finally definitions of the callback handler we want to use to collect user credentials.
The following figure shows default the CallbackHandler, which is fired to collect username and password before the container lets the application invoke a method with security constraint.

We can change the default CallbackHandler in application-client.xml by specifying a new Callbackhandler. The new callback should implement the javax.security.auth.callback.CallbackHandler. The following snippet shows the callback-handler element in application-client.xml.

[code lang=”java”]
<callback-handler>
book.glassfish.security.chapter3.SwingCallbackHandler
</callback-handler>
[/code]

We can use a programmatic way to provide the ACC with username and password instead of using the callback mechanism to have more control over the authentication procedures. To conduct programmatic login we can use com.sun.appserv.security.ProgrammaticLogin class to login before we access any EJB method which has security constraints, defining security measures for communication over IIOP. We can use the GlassFish-specific deployment descriptor for EJB modules to define several types of configuration elements. We can use one set of these elements to define security measures for communication between the EJB container and the clients over IIOP (Internet Inter-Orb Protocol).
The super element for the IOR security is ior-security-config, which includes the following sub elements:

  • The transport-config for specifying transport security
  • The sas-context for specifying the caller propagation options
  • The as-context for specifying the authentication method, the security realm
    we want to use for authentication.

Following snippet shows what we should include in the EJB deployment descriptor to get SSL transport security along with username and password-based authentication using the LDAPRealm we defined in Chapter 2.

[code lang=”xml”]
<ior-security-config>
<transport-config>
<integrity>required</integrity>
<confidentiality>required</confidentiality>
<establish-trust-in-target>Required
</establish-trust-in-target>
<establish-trust-in-client>none</establish-trust-in-client>
</transport-config>
<as-context>
<auth-method>username_password</auth-method>
<realm>LDAPRealm</realm>
<required>true</required>
</as-context>
<sas-context>
<caller-propagation>supported</caller-propagation>
</sas-context>
</ior-security-config>
[/code]

Starting from the top, this snippet instructs the EJB container’s IIOP listener to use SSL for  data transmission to ensure the integrity and confidentiality of data which is transferred between client and server. Other possible values for integrity and confidentiality elements are Supported and None, which means server supports SSL if requested by clients or it does not provide them even if the client asks for data
integrity and confidentiality.
We can have SSL mutual authentication by changing the value of establish-trustin-target and establish-trust-in-client to required. This way the client will authenticate itself to the server using its digital certificate and in the same way the server will authenticate itself to the client using the digital certificate we specified for IIOP listeners.
When using mutual authentication, we should ensure that the trust store of the client trusts the certificate of the server and the trust store of the server trusts the certificate of the client. To achieve this we should:

  1. Add the digital certificate of the client’s certificate issuer to the server
    trust store.
  2. Include the digital certificate of the server’s certificate issuer to the client’s
    trust store.

Later in the code snippet we have the as-context element that we can use to specify which authentication method and security realm we want to use for authenticating clients that need to invoke a secure method of an EJB. The only supported authentication method is USERNAME_PASSWORD. The last element is sas-context. We can use it to specify whether EJB container accepts propagated caller identities or not. Possible values are Supported, Required, and None.

Configuring Application Client Container security

The Application Client Container hosts a Java SE layer application that interacts with the EJB container of the application server using IIOP. Each instance of the container can only host one instance of the client application and can be configured for that client application instance.

When we want to run a client application deployed in GlassFish
we can either use Java Web Start or the script file provided in the
GlassFish bin directory. Command format for using the script file is
as follow:
./appclient -client /opt/dev/Conversion-app-client.
jar -xml /opt/dev/sun-acc.xml
It means that we want to launch the Conversion-app-client.jar
using a configuration file named sun-acc.xml.

The sun-acc.xml structure follows the schema defined in the http://www.sun.com/software/appserver/dtds/sun-application-client-container_1_2.dtd and allows us to configure every aspect of the ACC. The following shows the content of sun-acc.xml, which has both authentication and transport security configured.

[code lang=”xml”]
<client-container>
<target-server name="localhost" address="127.0.0.1" port="3700">
<security>
<ssl cert-nickname="s1as"
ssl2-enabled="false"
ssl2-ciphers="-rc4,-rc4export,-rc2,-rc2export,-des,
-desede3"
ssl3-enabled="true"
ssl3-tls-ciphers="+rsa_rc4_128_md5,
-rsa_rc4_40_md5,+rsa3_des_sha,+rsa_des_sha,
-rsa_rc2_40 _md5,-rsa_null_md5,-rsa_des_56_sha,
-rsa_rc4_56_sha"
tls-enabled="true"
tls-rollback-enabled="true"/>
<cert-db path="ignored" password="ignored"/>
<!– not used –>
</security>
<auth-realm name="LDAPRealm"
classname="com.sun.enterprise.security.auth.realm.ldap.LDAPRealm">
<property name="directory"
value="ldap://127.0.0.1:1389"/>
<property name="base-dn" value=" dc=example,dc=com "/>
<property name="search-bind-password" value="123456"/>
<property name="jaas-context" value="ldapRealm"/>
</auth-realm>
</target-server>
<client-credential user-name="james" password="james"/>
</client-container>
[/code]

Starting from the top, we are instructing the container to use a certificate identified by client nickname. Later on we will see how we can specify which keystore and trust store we want our client container to use when we launch our application. All other properties of the ssl element specify which SSL version and cipher suites are available to the ACC to choose from. During the negotiation between server and
client to establish an SSL session, the strongest cipher suite supported by both server and client is selected. In addition to configuring the transport security we can configure the authentication mechanism for ACC in order to let ACC collect the identification information and
send them back to server when required. Following the security element we have the auth-realm element which specifies the authentication realm that ACC must use to conduct the authentication. You should know all of these properties as we discussed them in great detail
in Chapter 2. The only thing that you should remember is the fact that this configuration has nothing to do with the LDAP realm we configured in the server. This configuration affects only the client container instance running in the client machine and using this particular sun-acc.xml file.

The Application Client Container process exists in the clients machine
and anything we configure using the sun-acc.xml affects the client
machines and has nothing to do with the server or other clients, which
run another instance of the application client.

Next we have the client-credential element which we can use to specify the default client credential that ACC sends to server instead of collecting the username and password. This element ensures that a single principal is used for all invocation without end users knowing about it.
Using SSL always bring out the issue of keystore and trust store which the application requires using during the SSL handshake and SSL session. There is no vendor-specific way to pass the trust and key store information to Java runtime and rather we can use the JVM environment variables to set these values. When JVM starts and needs to use SSL, it looks for some environment variables to
initiate the SSL session. These variables are included in the following table.


In Linux, we can use the following command to export these variables before launching the application client using the appclient script.

[code]
export VMARGS="-Djavax.net.ssl.keyStore=key-store-path -Djavax.net.ssl.
trustStore= trust-store-path -Djavax.net.ssl.keyStorePassword=key-storepassword
-Djavax.net.ssl.trustStorePassword=trust-store-password"
[/code]

For Microsoft Windows we can use the set command to set VMARGS value as follows:

[code]
set VMARGS="-Djavax.net.ssl.keyStore=key-store-path -Djavax.net.ssl.
trustStore=trust-store-path -Djavax.net.ssl.keyStorePassword=key-storepassword
-Djavax.net.ssl.trustStorePassword=trust-store-password"
[/code]

To create a working pair of certification stores we can follow the same steps we followed to create keystore and trust store for GlassFish application server. Using the same certificate issuer will guarantee that GlassFish will accept the certificate provided by the client and the client will accept the certificate provided by GlassFish. Now that we have set the required runtime arguments for JVM we can run the client
application and be assured about data confidentiality and integrity. The sample application for this chapter is included in the source code archive of the book.

Summary

In this chapter we studied Java EE security in action and developed a secure Java EE application with all of standard modules including EJB, Web, and application clients. We studied how we can secure EJBs using annotation and then use a web frontend to use the secure EJBs after the user provides correct identification information. We developed a client application to access the secure EJB and later on we studied how
we can use SSL and mutual authentication between the application client module and EJB container. In the next two chapters we will look at GlassFish security independent of the Java EE security and what measures we should consider to have a safe GlassFish installation.

Filed Under: Java EE Tagged With: Glassfish, Security

How to Configure Java Messaging Service (JMS) in GlassFish 3 Application Server?

September 10, 2010 by itadmin Leave a Comment

This book begins with the installation of Glassfish 3 and deploying Java applications. It also explains how to develop, configure, package, and deploy servlets. Additionally, we will learn the processing of HTML forms. As we move on, we will develop Java Server Pages and get to know about implicit JSP objects. We will also get to know about all the JSTL (JSP Standard Tag Library) tag libraries. This book gives us a better understanding on how to manage data from a database through the Java Database Connectivity (JDBC) API and the Java Persistence API (JPA). We will also learn more about the newly introduced features of JPA 2.0 and develop JSF 2.0 applications to learn how to customize them. We will then set up Glassfish for the Java Messaging (JMS) API and understand the working of message queues and message topics. Later, we will use the Context and Dependency Injection (CDI) API to integrate application layers and study the SOAP-based web service development using the JAX-WS specification. Finally, we will learn more about the RESTful web service development using the JAX-RS specification.

also read:

  • Java EE Tutorials
  • Java EE 7 Tutorials
  • Java EE Interview Questions

The book covers the various Java EE 6 conventions and annotations that can simplify enterprise Java application development. The latest versions of the Servlet, JSF, JPA, EJB, and JAX-WS specifications are covered, as well as new additions to the specification, such as JAX-RS and CDI.

What This Book Covers

Chapter 1, Getting Started with GlassFish will discuss how to download and install GlassFish. We will look at several methods of deploying a Java EE application through the GlassFish web console, through the asadmin command, and by copying the file to the autodeploy directory. We will cover basic GlassFish administration tasks such as setting up domains and setting up database connectivity by adding connection pools and data sources.

Chapter 2, Servlet Development and Deployment will cover how to develop, configure, package, and deploy servlets. We will also cover how to process HTML form information by accessing the HTTP request object. Additionally, forwarding HTTP requests from one servlet to another will be explained, as well as redirecting the HTTP response to a different server. We will discuss how to persist objects in memory across requests by attaching them to the servlet context and the HTTP session. Finally, we will look at all the major new features of Servlet 3.0, including configuring web applications via annotations, pluggability through web-fragment. xml , programmatic servlet configuration, and asynchronous processing.
Chapter 3, JavaServer Pages will talk about how to develop and deploy simple JSPs. We will cover how to access implicit objects such as request, session, and so on, from JSPs. Additionally, we will look at how to set and get the values of JavaBean properties via the <jsp:useBean> tag. In addition to that, we will find out how to include a JSP into another JSP at runtime via the <jsp:include> tag, and at compilation time via the JSP include directive. We will discuss how to write custom JSP tags by extending javax.servlet.jsp.tagext.SimpleTagSupport or by writing TAG files. We will also discuss how to access JavaBeans and their properties via the Unified Expression Language. Finally, we will cover the JSP XML syntax that allows us to develop XMLcompliant
JavaServer Pages.
Chapter 4, JSP Standard Tag Library will cover all JSP Standard Tag Library tags, including the core, formatting, SQL, and XML tags. Additionally, JSTL functions will be explained. Examples illustrating the most common JSTL tags and functions will be provided; additional JSTL tags and functions will be mentioned and described.
Chapter 5, Database Connectivity will talk about how to access data in a database via both the Java Database Connectivity (JDBC) and through the Java Persistence API (JPA). Defining both unidirectional and bidirectional one-to-one, one-to-many, and many-to-many relationships between JPA entities will be covered. Additionally, we will discuss how to use JPA composite primary keys by developing custom primary key classes. We will also discuss how to retrieve entities from a database by using the Java Persistence Query Language (JPQL). We will look at how to build queries programmatically through the JPA 2.0 Criteria API and automating data validation through JPA 2.0’s Bean Validation support
Chapter 6,JavaServer Faces will cover how to develop web-based applications using JavaServer Faces—the standard component framework for the Java EE 5 platform. We will talk about how to write a simple application by creating JSPs containing JSF tags and managed beans. We will discuss how to validate user input by using JSF’s standard validators and by creating our own custom validators, or by writing validator methods. Additionally, we will look at how to customize standard JSF error messages; both the message text and the message style (font, color, and so on). Finally, we will discuss how to write applications by integrating JSF and the Java Persistence API (JPA).
Chapter 7, Java Messaging Service will talk about how to set up JMS connection factories, JMS message queues, and JMS message topics in GlashFish using the GlashFish web console. We will cover how to send and receive messages to and from a message queue. We will discuss how to send and receive messages to and from a JMS message topic. We will find out how to browse messages in a message queue without
removing the messages from the queue. Finally, we will look at how to set up and interact with durable subscriptions to JMS topics.
Chapter 8, Security will talk about how to use GlashFish’s default realms to authenticate our web applications. We will cover the file realm, which stores user information in a flat file, and the certificate realm, which requires client-side certificates for user authentication. Additionally, we will discuss how to create additional realms that behave just like the default realms, by using the realm classes included with GlashFish.
Chapter 9, Enterprise JavaBeans will cover how to implement business logic via stateless and stateful session beans. Additionally, we will explain the concept of containermanaged transactions and bean-managed transactions. We will look at the life cycles for the different types of Enterprise Java Beans. We will talk about how to have EJB methods invoked periodically by the EJB container, by taking advantage of the EJB timer service. Finally, we will explain how to make sure that EJB methods are only invoked by authorized users.
Chapter 10, Contexts and Dependency Injection will talk about how JSF pages can access CDI named beans as if they were JSF managed beans. We will explain how CDI makes it easy to inject dependencies into our code. We will discuss how we can use qualifiers to determine what specigic implementation of dependency to inject into our code. Finally, we will look at all the scopes that a CDI bean can be placed into.
Chapter 11, Web Services with JAX-WS will cover how to develop web services and web service clients via the JAX-WS API. We will discuss how to send attachments to a web service. We will explain how to expose an EJB’s methods as web services. Finally, we will look at how to secure web services so that they are not accessible to unauthorized clients.
Chapter 12, RESTful Web Services with Jersey and JAX-RS will discuss how to easily develop RESTful web services using JAX-RS—a new addition to the Java EE specification. We will explain how to automatically convert data between Java and XML by taking advantage of the Java API for XML Binding (JAXB). Finally, we will cover how to pass parameters to our RESTful web services via the @PathParam and
@QueryParam annotations.

The Java Messaging API (JMS) provides a mechanism for Java EE applications to send messages to each other. JMS applications do not communicate directly, instead message producers send messages to a destination and message consumers receive the message from the destination.
The message destination is a message queue when the point-to-point (PTP) messaging domain is used, or a message topic when the publish/subscribe (pub/sub) messaging domain is used. In this chapter, we will cover the following topics:

  • Setting up GlashFish for JMS
  • Working with message queues
  • Working with message topics

Setting up GlassFish for JMS

Before we start writing code to take advantage of the JMS API, we need to configure some GlashFish resources. Specifically, we need to set up a JMS connection factory, a message queue, and a message topic.

Setting up a JMS connection factory

The easiest way to set up a JMS connection factory is via GlashFish’s web console. Recall from Chapter 1 that the web console can be accessed by starting our domain, by entering the following command in the command line:

[code lang=”java”]
asadmin start-domain domain1
[/code]

Then point the browser to http://localhost:4848 and log in:


A connection factory can be added by expanding the Resources node in the tree at the left-hand side of the web console, expanding the JMS Resources node and clicking on the Connection Factories node, then clicking on the New… button in the main area of the web console.


For our purposes, we can take most of the defaults. The only thing we need to do is enter a Pool Name and pick a Resource Type for our connection factory.

It is always a good idea to use a Pool Name starting with “jms/” when
picking a name for JMS resources. This way JMS resources can be
easily identified when browsing a JNDI tree.

In the text field labeled Pool Name, enter jms/GlassFishBookConnectionFactory. Our code examples later in this chapter will use this JNDI name to obtain a reference to this connection factory.
The Resource Type drop-down menu has three options:

  • javax.jms.TopicConnectionFactory – used to create a connection factory that creates JMS topics for JMS clients using the pub/sub messaging domain
  • javax.jms.QueueConnectionFactory – used to create a connection factory that creates JMS queues for JMS clients using the PTP messaging domain
  • javax.jms.ConnectionFactory – used to create a connection factory that creates either JMS topics or JMS queues

For our example, we will select javax.jms.ConnectionFactory. This way we can use
the same connection factory for all our examples, those using the PTP messaging
domain and those using the pub/sub messaging domain.
After entering the Pool Name for our connection factory, selecting a connection
factory type, and optionally entering a description for our connection factory,
we must click on the OK button for the changes to take effect.


We should then see our newly created connection factory listed in the main area of the GlashFish web console.

Setting up a JMS message queue

A JMS message queue can be added by expanding the Resources node in the tree at the left-hand side of the web console, expanding the JMS Resources node and clicking on the Destination Resources node, then clicking on the New… button in the main area of the web console.


In our example, the JNDI name of the message queue is jms/GlassFishBookQueue. The resource type for message queues must be javax.jms.Queue. Additionally, a Physical Destination Name must be entered. In this example, we use GlassFishBookQueue as the value for this field.
After clicking on the New… button, entering the appropriate information for our message queue, and clicking on the OK button, we should see the newly created queue:

Setting up a JMS message topic

Setting up a JMS message topic in GlashFish is very similar to setting up a message queue. In the GlashFish web console, expand the Resources node in the tree at the left hand side, then expand the JMS Resouces node and click on the Destination Resources node, then click on the New… button in the main area of the web console.


Our examples will use a JNDI Name of jms/GlassFishBookTopic. As this is a message topic, Resource Type must be javax.jms.Topic. The Description field is optional. The Physical Destination Name property is required. For our example, we will use GlassFishBookTopic as the value for this property.
After clicking on the OK button, we can see our newly created message topic:


Now that we have set up a connection factory, a message queue, and a message topic, we are ready to start writing code using the JMS API.

Message queues

Like we mentioned earlier, message queues are used when our JMS code uses the point-to-point (PTP) messaging domain. For the PTP messaging domain, there is usually one message producer and one message consumer. The message producer and the message consumer don’t need to run concurrently in order to communicate. The messages placed in the message queue by the message producer will stay in the
message queue until the message consumer executes and requests the messages from the queue.

Sending messages to a message queue

The following example illustrates how to add messages to a mess age queue:

[code lang=”java”]
package net.ensode.glassfishbook;
import javax.annotation.Resource;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
public class MessageSender
{
@Resource(mappedName = &quot;jms/GlassFishBookConnectionFactory&quot;)
private static ConnectionFactory connectionFactory;
@Resource(mappedName = &quot;jms/GlassFishBookQueue&quot;)
private static Queue queue;

public void produceMessages()
{
MessageProducer messageProducer;
TextMessage textMessage;
try
{
Connection connection = connectionFactory.createConnection();
Session session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
messageProducer = session.createProducer(queue);
textMessage = session.createTextMessage();
textMessage.setText(&quot;Testing, 1, 2, 3. Can you hear me?&quot;);
System.out.println(&quot;Sending the following message: &quot;
+ textMessage.getText());
messageProducer.send(textMessage);
textMessage.setText(&quot;Do you copy?&quot;);
System.out.println(&quot;Sending the following message: &quot;
+ textMessage.getText());
messageProducer.send(textMessage);
textMessage.setText(&quot;Good bye!&quot;);
System.out.println(&quot;Sending the following message: &quot;
+ textMessage.getText());
messageProducer.send(textMessage);
messageProducer.close();
session.close();
connection.close();
}
catch (JMSException e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
new MessageSender().produceMessages();
}
}
[/code]

Before delving into the details of this code, alert readers might have noticed that this class is a standalone Java application as it contains a main method. As this class is standalone, it executes outside the application server. In spite of this, we can see that some resources are injected into it, specifically the connection factory and queue. The reason we can inject resources into this code, even though it runs outside the application server, is because GlashFish includes a utility called appclient. This utility allows us to “wrap” an executable JAR file and allows it to have access to the application server resources. To execute the previous code, assuming it is packaged in an executable JAR file called jmsptpproducer.jar, we would type the following command in the command line:

[code lang=”java”]
appclient -client jmsptpproducer.jar
[/code]

We would then see, after some GlashFish log entries, the following output on the console:

[code lang=”java”]
Sending the following message: Testing, 1, 2, 3. Can you hear me?
Sending the following message: Do you copy?
Sending the following message: Good bye!
[/code]

The appclient executable can be found under [GlashFish installation directory]/GlashFish/bin. The previous example assumes this directory is in your PATH variable. If it isn’t the complete path to the appclient executable, it must be typed in the command line.
With that out of the way, we can now explain the code. The produceMessages() method performs all the necessary steps to send messages
to a message queue. The first thing this method does is obtain a JMS connection by invoking the createConnection() method on the injected instance of javax.jms. ConnectionFactory. Notice that the mappedName attribute of the @Resource annotation decorating the connection factory object matches the JNDI name of the connection factory we set up in the GlashFish web console. Behind the scenes, a JNDI lookup is made using this name to obtain the connection factory object. After obtaining a connection, the next step is to obtain a JMS session from said
connection. This can be accomplished by calling the createSession() method on the Connection object. As can be seen in the previous code, the createSession() method takes two parameters.
The first parameter of the createSession() method is a Boolean indicating if the session is transacted. If this value is true, several messages can be sent as part of a transaction by invoking the commit() method in the session object. Similarly, they can be rolled back by invoking its rollback() method.
The second parameter of the createSession() method indicates how messages are acknowledged by the message receiver. Valid values for this parameter are defined as constants in the javax.jms.Session interface.

  • Session.AUTO_ACKNOWLEDGE: indicates that the session will automatically acknowledge the receipt of a message.
  • Session.CLIENT_ACKNOWLEDGE: indicates that the message receiver must explicitly call the acknowledge() method on the message.
  • Session.DUPS_OK_ACKNOWLEDGE: indicates that the session will lazily acknowledge the receipt of messages. Using this value might result in some messages being delivered more than once.

After obtaining a JMS session, an instance of javax.jms.MessageProducer is obtained by invoking the createProducer() method on the session object. The MessageProducer object is the one that will actually send messages to the message queue. The injected Queue instance is passed as a parameter to the createProducer() method . Again, the value of the mappedName attribute for the @Resource annotation decorating this object must match the JNDI name we gave our message queue when setting it up in the GlashFish web console.
After obtaining an instance of MessageProducer, the code creates a series of text messages by invoking the createTextMessage() method on the session object. This method returns an instance of a class implementing the javax.jms.TextMessage interface. This interface defines a method called setText() , which is used to set the actual text in the message. After creating each text message and setting its text, they are
sent to the queue by invoking the send() method on the MessageProducer object. After sending the messages, the code disconnects from the JMS queue by invoking the close() method on the MessageProducer object , on the Session object , and on the Connection object.
Although the previous example sends only text messages to the queue, we are not limited to this type of message. The JMS API provides several types of messages that can be sent and received by JMS applications. All message types are defined as interfaces in the javax.jms package. The following table lists all the available message types:


For more information on all of these message types, consult their JavaDoc documentation at http://java.sun.com/javaee/6/docs/api/.

Retrieving messages from a message queue

There is no point in sending messages from a queue if nothing is going to receive them. The following example illustrates how to retrieve messages from a JMS message queue:

[code lang=”java”]
package net.ensode.glassfishbook;
import javax.annotation.Resource;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;

public class MessageReceiver
{
@Resource(mappedName = &quot;jms/GlassFishBookConnectionFactory&quot;)
private static ConnectionFactory connectionFactory;
@Resource(mappedName = &quot;jms/GlassFishBookQueue&quot;)
private static Queue queue;

public void getMessages()
{
Connection connection;
MessageConsumer messageConsumer;
TextMessage textMessage;
boolean goodByeReceived = false;
try
{
connection = connectionFactory.createConnection();
Session session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
messageConsumer = session.createConsumer(queue);
connection.start();
while (!goodByeReceived)
{
System.out.println(&quot;Waiting for messages…&quot;);
textMessage = (TextMessage) messageConsumer.receive();
if (textMessage != null)
{
System.out.print(&quot;Received the following message: &quot;);
System.out.println(textMessage.getText());
System.out.println();
}
if (textMessage.getText() != null
&amp;&amp; textMessage.getText().equals(&quot;Good bye!&quot;))
{
goodByeReceived = true;
}
}
messageConsumer.close();
session.close();
connection.close();
}
catch (JMSException e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
new MessageReceiver().getMessages();
}
}
[/code]

Just like in the previous example, an instance of javax.jms.ConnectionFactory and an instance of javax.jms.Queue are injected by using the @Resource annotation. Getting a connection and a JMS session is exactly the same as in the previous example.  In this example, we obtain an instance of javax.jms.MessageConsumer by calling the createConsumer() method on the JMS session object. When we are ready to
start receiving messages from the message queue, we need to invoke the start() method on the JMS connection object.

Code not receiving messages?
A common mistake when writing JMS messages is to fail to call the
start() method on the JMS connection object. If our code is not
receiving messages it should be receiving, we need to make sure we
didn’t forget to call this method.

Messages are received by invoking the receive() method on the instance of MessageConsumer obtained from the JMS session. This method returns an instance of a class implementing the javax.jms.Message interface. It must be casted to the appropriate type in order to obtain the actual message. In this particular example, we placed this method call in a while loop, as we are expecting a message that will let us know that no more messages are coming. Specifically, we are looking for a message containing the text “Good bye!”. Once we receive said message, we break out of the loop and continue processing. In this particular case, there is no more processing to do. Therefore, all we do is call the
close() method on the message consumer object, on the session object, and on the connection object.
Just like in the previous example, using the appclient utility allows us to inject resources into the code and prevents us from having to add any libraries to the CLASSPATH. After executing the code through the appclient utility, we should see the following output in the command line:

[code lang=”java”]
appclient -client target/jmsptpconsumer.jar
Waiting for messages…
Received the following message: Testing, 1, 2, 3. Can you hear me?

Waiting for messages…
Received the following message: Do you copy?

Waiting for messages…
Received the following message: Good bye!
[/code]

This of course assumes that the previous example was already executed and it placed the messages in the message queue.

Asynchronously receiving messages from a message queue

The MessageConsumer.receive() method has a disadvantage—it blocks execution until a message is received from the queue. We can avoid this disadvantage by receiving messages asynchronously via an implementation of the javax.jms.MessageListener interface. The javax.jms.MessageListener interface contains a single method called onMessage. It takes an instance of a class implementing the javax.jms.Message interface as its sole parameter. The following example illustrates a typical implementation of this interface:

[code lang=”java”]
package net.ensode.glassfishbook;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
public class ExampleMessageListener implements MessageListener
{
@Override
public void onMessage(Message message)
{
TextMessage textMessage = (TextMessage) message;
try
{
System.out.print(&quot;Received the following message: &quot;);
System.out.println(textMessage.getText());
System.out.println();
}
catch (JMSException e)
{
e.printStackTrace();
}
}
}
[/code]

In this case, the onMessage() method simply outputs the message text to the console. Our main code can now delegate message retrieval to our custom MessageListener implementation:

[code lang=”java”]
package net.ensode.glassfishbook;
import javax.annotation.Resource;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.Queue;
import javax.jms.Session;
public class AsynchMessReceiver
{
@Resource(mappedName = &quot;jms/GlassFishBookConnectionFactory&quot;)
private static ConnectionFactory connectionFactory;
@Resource(mappedName = &quot;jms/GlassFishBookQueue&quot;)
private static Queue queue;
public void getMessages()
{
Connection connection;
MessageConsumer messageConsumer;
try
{
connection = connectionFactory.createConnection();
Session session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
messageConsumer = session.createConsumer(queue);
messageConsumer.setMessageListener(new
ExampleMessageListener());
connection.start();
System.out.println(&quot;The above line wil l allow the &quot;
+ &quot;MessageListener implementation to &quot;
+ &quot;receiving and processing messages from the queue.&quot;);
Thread.sleep(1000);
System.out.println(&quot;Our code does not have to block &quot;
+ &quot;while messages are received.&quot;);
Thread.sleep(1000);
System.out.println(&quot;It can do other stuff &quot;
+ &quot;(hopefully something more useful than sending &quot;
+ &quot;silly output to the console. :)&quot;);
Thread.sleep(1000);
messageConsumer.close();
session.close();
connection.close();
}
catch (JMSException e)
{
e.printStackTrace();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
new AsynchMessReceiver().getMessages();
}
}
[/code]

The only relevant difference between this example and the one in the previous section is that in this case, we are calling the setMessageListener() method on the instance of javax.jms.MessageConsumer obtained from the JMS session. We pass an instance of our custom implementation of javax.jms.MessageListener to this method. Its onMessage() method is automatically called whenever there is a message waiting in the queue. By using this approach, the main code does not block while waiting to receive messages. Executing the previous example (using of course GlashFish’s appclient utility) results in the following output:

[code]
appclient -client target/jmsptpasynchconsumer.jar
The above line will allow the MessageListener implementation to receiving
and processing messages from the queue.
Received the following message: Testing, 1, 2, 3. Can you hear me?

Received the following message: Do you copy?

Received the following message: Good bye!

Our code does not have to block while messages are received.
It can do other stuff (hopefully something more useful than sending silly
output to the console. 🙂
[/code]

Notice how the messages were received and processed while the main thread was executing. We can tell this is the case because the output of the onMessage() method of our MessageListener can be seen between calls to System.out.println() in the primary class.

Browsing message queues

JMS provides a way to browse message queues without actually removing the messages from the queue. The following example illustrates how to do this:

[code lang=”java”]
package net.ensode.glassfishbook;
import java.util.Enumeration;
import javax.annotation.Resource;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.Queue;
import javax.jms.QueueBrowser;
import javax.jms.Session;
import javax.jms.TextMessage;
public class MessageQueueBrowser
{
@Resource(mappedName = &quot;jms/GlassFishBookConnectionFactory&quot;)
private static ConnectionFactory connectionFactory;
@Resource(mappedName = &quot;jms/GlassFishBookQueue&quot;)
private static Queue queue;
public void browseMessages()
{
try
{
Enumeration messageEnumeration;
TextMessage textMessage;
Connection connection = connectionFactory.createConnection();

Session session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
QueueBrowser browser = session.createBrowser(queue);
messageEnumeration = browser.getEnumeration();
if (messageEnumeration != null)
{
if (!messageEnumeration.hasMoreElements())
{
System.out.println(&quot;There are no messages &quot; + &quot;in the
queue.&quot;);
}
else
{
System.out.println(&quot;The following messages are in the
queue:&quot;);
while (messageEnumeration.hasMoreElements())
{
textMessage =
(TextMessage) messageEnumeration.nextElement();
System.out.println(textMessage.getText());
}
}
}
session.close();
connection.close();
}
catch (JMSException e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
new MessageQueueBrowser().browseMessages();
}
}
[/code]

As we can see, the procedure to browse messages in a message queue is straightforward. We obtain a JMS connection and a JMS session the usual way, then invoke the createBrowser() method on the JMS session object. This method returns an implementation of the javax.jms.QueueBrowser interface. This interface contains a getEnumeration() method that we can invoke to obtain an enumeration containing all messages in the queue. To examine the messages in the queue, we simply traverse this enumeration and obtain the messages one by one. In the previous example, we simply invoke the getText() method of each message in the queue.

Message topics

Message topics are used when our JMS code uses the publish/subscribe (pub/sub) messaging domain. When using this messaging domain, the same message can be sent to all subscribers of the topic.

Sending messages to a message topic

The following example illustrates how to send messages to a message topic: [code lang=”java”]
[code lang=&quot;java&quot;] package net.ensode.glassfishbook;
import javax.annotation.Resource;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
public class MessageSender
{
@Resource(mappedName = &quot;jms/GlassFishBookConnectionFactory&quot;)
private static ConnectionFactory connectionFactory;
@Resource(mappedName = &quot;jms/GlassFishBookTopic&quot;)
private static Topic topic;
public void produceMessages()
{
MessageProducer messageProducer;
TextMessage textMessage;
try
{
Connection connection = connectionFactory.createConnection();
Session session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
messageProducer = session.createProducer(topic);
textMessage = session.createTextMessage();
textMessage.setText(&quot;Testing, 1, 2, 3. Can you hear me?&quot;);
System.out.println(&quot;Sending the following message: &quot;
+ textMessage.getText());
messageProducer.send(textMessage);
textMessage.setText(&quot;Do you copy?&quot;);
System.out.println(&quot;Sending the following message: &quot;
+ textMessage.getText());
messageProducer.send(textMessage);
textMessage.setText(&quot;Good bye!&quot;);
System.out.println(&quot;Sending the following message: &quot;
+ textMessage.getText());
messageProducer.send(textMessage);
messageProducer.close();
session.close();
connection.close();
}
catch (JMSException e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
new MessageSender().produceMessages();
}
}
[/code]

As we can see, this code is nearly identical to the MessageSender class we saw when we discussed point-to-point messaging. As a matter of fact, the only lines of code that are different are the ones that are highlighted. The JMS API was designed this way so that application developers do not have to learn two different APIs for the PTP and pub/sub domains. As the code is nearly identical to the corresponding example in the Message queues section, we will only explain the differences between the two examples. In this example, instead of declaring an instance of a class implementing javax.jms. Queue, we declare an instance of a class implementing javax.jms.Topic. Just like in the previous examples, we use dependency injection to initialize the Topic object. After obtaining a JMS connection and a JMS session, we pass the Topic object to the createProducer() method in the Session object. This method returns an instance of javax.jms.MessageProducer that we can use to send messages to the JMS topic.

Receiving messages from a message topic

Just as sending messages to a message topic is nearly identical to sending messages to a message queue, receiving messages from a message topic is nearly identical to receiving messages from a message queue.

[code lang=”java”]
package net.ensode.glassfishbook;
import javax.annotation.Resource;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
public class MessageReceiver
{
@Resource(mappedName = &quot;jms/GlassFishBookConnectionFactory&quot;)
private static ConnectionFactory connectionFactory;
@Resource(mappedName = &quot;jms/GlassFishBookTopic&quot;)
private static Topic topic;
public void getMessages()
{
Connection connection;
MessageConsumer messageConsumer;
TextMessage textMessage;
boolean goodByeReceived = false;
try
{
connection = connectionFactory.createConnection();
Session session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
messageConsumer = session.createConsumer(topic);
connection.start();
while (!goodByeReceived)
{
System.out.println(&quot;Waiting for messages…&quot;);
textMessage = (TextMessage) messageConsumer.receive();
if (textMessage != null)
{
System.out.print(&quot;Received the following message: &quot;);
System.out.println(textMessage.getText());
System.out.println();
}
if (textMessage.getText() != null
&amp;&amp; textMessage.getText().equals(&quot;Good bye!&quot;))
{
goodByeReceived = true;
}
}
messageConsumer.close();
session.close();
connection.close();
}
catch (JMSException e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
new MessageReceiver().getMessages();
}
}
[/code]

Once again, the differences between this code and the corresponding code for PTP are trivial. Instead of declaring an instance of a class implementing javax.jms.Queue, we declare a class implementing javax.jms.Topic. We use the @Resource annotation to inject an instance of this class into our code using the JNDI name we used when creating it in the GlashFish web console. After obtaining a JMS connection and a JMS session, we pass the Topic object to the createConsumer() method in the Session object. This method returns an instance of javax.jms.MessageConsumer that we can use to receive messages from the JMS topic. Using the pub/sub messaging domain as illustrated in this section has the advantage that messages can be sent to several message consumers. This can be easily tested by concurrently executing two instances of the MessageReceiver class we developed in this section, then executing the MessageSender class we developed in the previous section. We should see console output for each instance, indicating that both instances received all messages. Just like with message queues, messages can be retrieved asynchronously from a message topic. The procedure to do this is so similar to the message queue version that we will not show an example. To convert the asynchronous example shown earlier in this chapter to use a message topic, simply replace the javax.jms.Queue variable with an instance of javax.jms.Topic and inject the appropriate instance by using “jms/GlassFishBookTopic” as the value of the mappedName attribute of the @Resource annotation decorating the instance of javax.jms.Topic.

Creating durable subscribers

The disadvantage of using the pub/sub messaging domain is that message consumers must be executing when messages are sent to the topic. If the message consumer is not executing at the time, it will not receive the messages, whereas in PTP, messages are kept in a queue until the message consumer executes. Fortunately, the JMS API provides a way to use the pub/sub messaging domain and keep messages in the topic until all subscribed message consumers execute and receive the message. This can be accomplished by creating durable subscribers to a JMS topic. In order to be able to service durable subscribers, we need to set the ClientId property of our JMS connection factory. Each durable subscriber must have a unique client id, therefore a unique connection factory must be declared for each potential durable subscriber.

InvalidClientIdException?
Only one JMS client can connect to a topic for a specific client id. If more
than one JMS client attempts to obtain a JMS connection using the same
connection factory, a JMSException stating that the client id is already in
use will be thrown. The solution is to create a connection factory for each
potential client that will be receiving messages from the durable topic.

Like we mentioned before, the easiest way to add a connection factory is through the GlashFish web console. Recall that to add a JMS connection factory through the GlashFish web console, we need to expand the Resources node on the left hand side, then expand the JMS Resources node, click on the Connection Factories node, and click on the New… button in the main area of the page. Our next example will use the settings displayed in the following screenshot:


Before clicking on the OK button, we need to scroll to the bottom of the page, click on the Add Property button, and enter a new property named ClientId. Our example will use ExampleId as the value for this property.


Now that we have set up GlashFish to be able to provide durable subscriptions, we are ready to write some code to take advantage of them:

[code lang=”java”]
package net.ensode.glassfishbook;
import javax.annotation.Resource;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
public class MessageReceiver
{
@Resource(mappedName = &quot;jms/GlassFishBookDurableConnectionFactory&quot;)
private static ConnectionFactory connectionFactory;
@Resource(mappedName = &quot;jms/GlassFishBookTopic&quot;)
private static Topic topic;
public void getMessages()
{
Connection connection;
MessageConsumer messageConsumer;
TextMessage textMessage;
boolean goodByeReceived = false;
try
{
connection = connectionFactory.createConnection();
Session session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
messageConsumer = session.createDurableSubscriber(topic,
&quot;Subscriber1&quot;);
connection.start();
while (!goodByeReceived)
{
System.out.println(&quot;Waiting for messages…&quot;);
textMessage = (TextMessage) messageConsumer.receive();
if (textMessage != null)
{
System.out.print(&quot;Received the following message: &quot;);
System.out.println(textMessage.getText());
System.out.println();
}
if (textMessage.getText() != null
&amp;&amp; textMessage.getText().equals(&quot;Good bye!&quot;))
{
goodByeReceived = true;
}
}
messageConsumer.close();
session.close();
connection.close();
}
catch (JMSException e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
new MessageReceiver().getMessages();
}
}
[/code]

As we can see, this code is not much different from the previous examples whose purpose was to retrieve messages. There are only two differences from the previous examples: the instance of ConnectionFactory to which we are injecting is the one we set up earlier in this section to handle durable subscriptions, and instead of calling the createSubscriber() method on the JMS session object, we are calling createDurableSubscriber() . The createDurableSubscriber() method takes two arguments: a JMS Topic object to retrieve messages from and a string designating a name for this subscription. This second parameter must be unique between all subscribers to the durable topic.

Summary

In this chapter, we covered how to set up JMS connection factories, JMS message queues, and JMS message topics in GlashFish using the GlashFish web console. We also covered how to send messages to a message queue via the javax.jms.MessageProducer interface.
Additionally, we covered how to receive messages from a message queue via the javax.jms.MessageConsumer interface. We also covered how to asynchronously receive messages from a message queue by implementing the javax.jms.MessageListener interface. We also saw how to use these interfaces to send and receive messages to and from a JMS message topic. We covered how to browse messages in a message queue without removing the messages from the queue via the javax.jms.QueueBrowser interface. Finally, we saw how to set up and interact with durable subscriptions to JMS topics.

Filed Under: Java EE Tagged With: Glassfish, JMS

JavaFX Media

September 6, 2010 by itadmin Leave a Comment

JavaFX 1.2 Application Development Cookbook

  • Buy JavaFX Books from Amazon Book Store

This book is a collection of code recipes, examples, and informative discourses designed to enable the reader to get started with creating JavaFX application quickly. The book is arranged as a series of loosely related code recipes that a reader can easily select to fit his or her needs. It exposes readers to a great variety of topics designed to satisfy different skill levels. Readers will learn about the language, animation techniques, paints, effects, JavaFX controls, integration of Swing components, styling with CSS, audio/video, deployment practices, and JavaFX integration with Adobe design tools.

also read:

  • Java FX Tutorials
  • Developing a Simple Todo Application using JavaFX, Java and MongoDB
  • Using JavaFX Chart API to add charts to Swing applications

What This Book Covers

Chapter 1, Getting Started with JavaFX… This is the “getting started” chapter of the book. It provides introductory materials to the platform, including installation instructions to get your environment set up. It also covers language basics such as classes, data types, function usage, variable declaration, data binding, triggers, Java and JavaFX integration.
Chapter 2, Creating JavaFX Applications… This chapter covers the essential building blocks of the JavaFX application framework, including primitive shapes, path, text, constructive area geometry, mouse/keyboard input, custom node, and window styling.
Chapter 3, Transformations, Animations, and Effects… This chapter explores the animation capabilities supported in JavaFX. You start with the Transition API to quickly build simple animations. The material continues to cover the KeyFrame API for more advanced animation sequences. You will learn about colors, effects, and how to create your own custom paint and effects.
Chapter 4, Components and Skinning… This chapter is divided into two sections. The first section shows readers how to use the set of standard JavaFX controls. The chapter also shows how to embed Swing components in your JavaFX scene graph. You will also learn how to create your own custom visual controls. The second section of the chapter introduces the reader to JavaFX‘s support for CSS. The reader will learn how to style controls using inline and externalized CSS to create skins.
Chapter 5, JavaFX Media… One of the exciting features of JavaFX is its inherent support for multimedia. JavaFX includes support for rendering of images in multiple formats and support for playback of audio and video on all platforms where JavaFX is supported. In
this chapter, readers learn how to display and manipulate images using the Image API. They will also learn how to playback both audio and video using the Media API. The chapter shows also how to create practical custom playback controls.
Chapter 6, Working with Data… JavaFX provides superb support for accessing and manipulating data both locally and remotely. In this chapter, readers are introduced to the Storage API for local data storage. It provides extensive coverage of JavaFX‘s HttpRequest API for accessing data on remote web servers. Readers will learn how to use JavaFX‘s XML and JSON parsers to build RESTful client mashups using popular services such as Google Map, Yahoo Weather, and Zillow Listing. Finally, the chapter explores JavaFX‘s built-in Chart API for data visualization.
Chapter 7, Deployment and Integration… This chapter provides coverage of the deployment mechanism supported by JavaFX. Readers will learn how to properly build and package their applications to target the different runtimes supported by JavaFX, including the web browser and the desktop. Readers learn how to create Java Web Startready applications using the build tools included in the SDK. The chapter shows how to write JavaScript that communicates with your JavaFX applet while running within the browser.
Chapter 8, The JavaFX Production Suite… This chapter covers JavaFX‘s integral support for designer tools from Adobe, including Illustrator and Photoshop. Readers are walked through the process of exporting creative assets using the JavaFX Production Suite
plugins available for these tools. The chapters also shows how to integrate exported objects from Photoshop and Illustrator into JavaFX.

JavaFX Media

In this chapter, we will cover the following topics:

  • Accessing media assets
  • Loading and displaying images with ImageView
  • Applying effects and transformations to images
  • Creating image effects with blending
  • Playing audio with MediaPlayer
  • Playing video with MediaView
  • Creating a media playback component

Introduction

One of the most celebrated features of JavaFX is its inherent support for media playback. As of version 1.2, JavaFX has the ability to seamlessly load images in different formats, play audio, and play video in several formats using its built-in components. To achieve platform independence and performance, the support for media playback in JavaFX is implemented as a two-tiered strategy:

  • Platform-independent APIs— the JavaFX SDK comes with a media API designed to provide a uniform set of interfaces to media functionalities. Part of the platform-independence offerings include a portable codec (On2’s VP6), which will play on all platforms where JavaFX media playback is supported.
  • Platform-dependent implementations— to boost media playback performance, JavaFX also has the ability to use the native media engine supported by the underlying OS. For instance, playback on the Windows platform may be rendered by the Windows DirectShow media engine (see next recipe).

This chapter shows you how to use the supported media rendering components, including ImageView, MediaPlayer, and MediaView. These components provide high-level APIs that let developers create applications with engaging and interactive media content.

Accessing media assets

In previous chapters, you have seen the use of variable _DIR__ when accessing local resources, but little detail was offered about its purpose and how it works. So, what does that special variable store? In this recipe, we will explore how to use the __DIR__ special variable and other means of loading resources locally or remotely.

Getting ready

The concepts presented in this recipe are used widely throughout the JavaFX application framework when pointing to resources. In general, classes that point to a local or remote resource uses a string representation of a URL where the resource is stored. This is especially true for the ImageView and MediaPlayer classes discussed in this chapter.

How to do it…

This recipe shows you three ways of creating a URL to point to a local or remote resource used by a JavaFX application. The full listing of the code presented here can be found in ch05/source-code/src/UrlAccess.fx.
Using the __DIR__ pseudo-variable to access assets as packaged resources:
[code lang=”java”]
var resImage = "{__DIR__}image.png";
[/code]
Using a direct reference to a local file:
[code lang=”java”]
var localImage =
"file:/users/home/vladimir/javafx/ch005/source-code/src/image.png";
[/code]
Using a URL to access a remote file:
[code lang=”java”]
var remoteImage = "http://www.flickr.com/3201/2905493571_a6db13ce1b_d.
jpg"
[/code]

How it works…

Loading media assets in JavaFX requires the use of a well-formatted URL that points to the location of the resources. For instance, both the Image and the Media classes (covered later in this chapter) require a URL string to locate and load the resource to be rendered. The URL must be an absolute path that specifies the fully-realized scheme, device, and resource location. The previous code snippets show the following three ways of accessing resources in JavaFX:

  • __DIR__ pseudo-variable— often, you will see the use of JavaFX‘s pseudo variable
    __DIR__, used when specifying the location of a resource. It is a special variable that stores the String value of the directory where the executing class that referenced __DIR__ is located. This is valuable, especially when the resource is embedded in the application’s JAR file. At runtime, __DIR__ stores the location of the resource in the JAR file, making it accessible for reading as a stream. In the previous code, for example, the expression {__DIR__}image.png explodes as jar:file:/users/home/vladimir/javafx/ch005/source-code/dist/source-code.jar!/image.png.
  • Direct reference to local resources—when the application is deployed as a desktop application, you can specify the location of your resources using URLs that provides the absolute path to where the resources are located. In our code, we use file:/users/home/vladimir/javafx/ch005/source-code/src/image.png as the absolute fully qualified path to the image file image.png.
  • Direct reference to remote resources—finally, when loading media assets, you are able to specify the path of a fully-qualified URL to a remote resource using HTTP.
    As long as there are no subsequent permissions required, classes such as Image and Media are able to pull down the resource with no problem. For our code, we use a URL to a Flickr image http://www.flickr.com/3201/2905493571_
    a6db13ce1b_d.jpg.

There’s more…

Besides __DIR__, JavaFX provides the _FILE__ pseudo variable as well. As you may well guess, __FILE__ resolves to the fully qualified path of the of the JavaFX script file that contains the __FILE__ pseudo variable. At runtime, when your application is compiled, this will be the script class that contains the __FILE__ reference.

Loading and displaying images with ImageView

If you have already checked out recipes in previous chapters, you know by now that JavaFX provides classes, which make it easy to load and display images. This recipe takes a closer look at the mechanics provided by the Image API to load and display images in your JavaFX applications.

Getting ready

This recipe uses classes from the Image API located in the javafx.scene.image package. Using this API, you are able to configure, load, and control how your images are displayed using the classes Image and ImageView . For this recipe, we will build a simple image browser to illustrate the concepts presented here. The browser allows users to load an image by providing its URL. You will use standard JavaFX controls, such as text boxes and buttons, to build the GUI. If you are not familiar with the standard GUI controls, review the recipe Creating a form with JavaFX controls from Chapter 4, Components and Skinning.

How to do it…

The code given next has been shortened to illustrate the essential portions involved in loading
and displaying an image. You can get a full listing of the code from ch05/source-code/src/image/ImageBrowserSimpleDemo.fx.
[code lang=”java”]
def w = 800;
def h = 600;
var scene:Scene;
def maxW = w * 0.9;
def maxH = h * 0.9;
def imgView:ImageView = ImageView{
preserveRatio:true
fitWidth: maxW fitHeight:maxH
layoutX:(w-maxW)/2 layoutY:(h-maxH)/2
};
function loadImg(){
view.image = Image{
url:(scene.lookup("addr") as TextBox).text
backgroundLoading:true
placeholder:Image{url:"{__DIR__}loading.jpg"}
}
}
def addrBar = Group{
layoutX: 20
layoutY: 20
content:HBox {
nodeVPos:VPos.CENTER
spacing:7
content:[
Label{text:"Image URL:" textFill:Color.SILVER}
TextBox{id:"addr" columns:80 promptText:"http://"
action:function(){loadImg()}
}
Button{id:"btnGo" text:"Get Image"
action:function(){loadImg()}
}
]
}
}
[/code]
When the variables imgView and addrBar are placed on the scene and the application is executed, you will get the results as shown in the following screenshot:

The image shown in this screenshot is licensed under creative common. For additional information and licensing details, go to http://www.flickr.com/photos/motleypixel/2905493571/sizes/m/.

How it works…

Loading and displaying images in JavaFX involves two classes, Image and ImageView. While
class Image is responsible for accessing and managing the binary stream of the image, ImageView, on the other hand, is of the type Node and is responsible for displaying the loaded image on the scene. The code presented in this recipe lets the user enter a URL for an image and loads the image on the screen. Let’s take a closer look at the code and how it works:

  • The ImageView—the first significant item to notice is the declaration of an ImageView instance assigned to the variable imgView. This is the component that will display the image on the scene when it is fully loaded. We specify the properties fitWidth, fitHeight, and preserveRatio . These properties will cause imgView to stretch (if the image is smaller than specified) or shrink (if the image is larger than specified) while preserving the aspect ratio of the image.
  • Image URL bar— the form that captures the URL of the image to load is grouped in the Group instance variable addrBar. The form consists of a Label, a TextBox, and a Button instance. The TextBox instance has several properties set, including id=”addr”, which allows us to find a reference to it in the code. Both the TextBox and the Button instances have their action properties defined as a function that invokes function loadImg(). Therefore, when the TextBox has focus and the Enter key is pressed, or when the Button instance is clicked on, the image will be loaded.
  • Loading the image—the image is loaded by calling the function l oadImg(). It
    assigns an instance of Image to imgView.image. For the Image.url property, we use the Scene.lookup(id:String) function to retrieve an instance of the TextBox using its id of addr. For images that may take a while to load, we set up the following two properties:
    • To ensure that the application does not hang while the image loads, the property backgroundLoading:Boolean is set to true. This causes the GUI to remain responsive while an image loads.
    • The property p laceholder:Image is used to specify a local image to use while the remote image is loading, as shown in the previous screenshot. For example, we use the local image {__DIR__}
      loading.png. It gets loaded immediately and remains on the screen while the remote image loads. When the remote image is loaded, it replaces the placeholder image.

There’s more…

Format support

As of version 1.2, JavaFX has inherent supports for the most popular image formats (popularity here = web-supported), which includes PNG, JPG, BMP, and GIF. If you have
requirements for formats other than these, such as TIFF for instance, you will have to take matters into your own hands and use external image libraries such as Java Advanced Imaging (JAI) API (not covered here).

Asynchronous loading issues

As mentioned in the previous section, when you are loading images from locations with high latency (over the network for instance), you can use the asynchronous background-loading option for your image. This causes the image-loading operation to occur in a separate execution thread to keep your GUI responsive.
This, however, presents an issue, whereby if you want to determine the dimensions of the image (which is available only after the image is fully downloaded), it will report zero when loading asynchronously, as shown in the next segment:
[code lang=”java”]
def img = Image{
url:"http://someimage.com/img.png"
backgroundLoading:true
}//does not wait here, it continues to next line
println (img.width); // prints 0
[/code]
This is because the image is still being downloaded on the Image thread, and the main GUI thread did not wait for completion and continues with its execution. Therefore, when we query the property width of Image, it will be zero.
Unfortunately in version 1.2, the Image class does not offer event notification functions to know when image is done loading. If your code relies on the actual size of the image to be known, you must block with asynchronous loading (by setting backgroundLoading = false) to wait for the image to download and get the size. Another way around is to specify the size of the image yourself by specifying the dimensions (see next sub-section on Image resize and aspect ratio).

Image resize and aspect ratio

Another feature supported by Image and ImageView is the automatic resizing of the image. The Image class will attempt to resize the image when a value is provided for the properties. width:Number or height:Number. ImageView will attempt to do the same when the properties fitWidth:Number and fitHeight:Number are specified. Both classes support property preserveRation:Boolean, which forces the resize operation to maintain the aspect ratio of the original image while resizing to the specified dimensions as shown next:
[code lang=”java”]
def imgView:ImageView = ImageView{
preserveRatio:true
&lt;B&gt;fitWidth:&lt;/B&gt; 200
};
[/code]
The previous code will resize the image to a width of 200 pixels. Because the preserveRatio property is true, the height of the image is automatically calculated. This is useful especially if you do not know the actual size of the image ahead of time (see previous section).

See also

  • Chapter 4—Creating a form with JavaFX controls
  • Introduction
  • Accessing media assets

Applying effects and transformations to images

Now that you have learned how to load images, what can you do with them? Well, since ImageView is an instance of the Node class, your loaded images can receive the same treatment you would ordinarily provide, shapes, for example. In this recipe, we are going to extend the example from the previous recipe, Loading and displaying images with ImageView, to add image manipulation functionalities.

Getting ready

In this recipe, we are going to reach back to some of the concepts learned in previous chapters to extend the image browser example presented in the previous recipe. We will make use of JavaFX GUI controls and node effects. If you are not familiar with either of these topics, please review the recipes from Chapter 3, Transformations, Animations, and Effects, and Chapter 4, Components and Skinning.
The example presented here extends the image browser from the previous recipe to add image manipulation capabilities. The new version adds GUI controls to scale, rotate, add effects, and animate the loaded image.

How to do it…

The code snippet presented next has been abbreviated to concentrate on the more interesting aspects of the code. You can access the full code listing from ch05/source-code/src/ image/ImageBrowserExtendedDemo.fx.
[code lang=”java”]
def w = 800;
def h = 600;
def maxW = w * 0.7;
def maxH = h * 0.7;
var scene:Scene;
def slider = Slider{min:1 max:1.5 value:1}
def imgView:ImageView = ImageView{
preserveRatio:true
fitWidth:bind if((slider.value*maxW) &lt; w)
maxW * slider.value else w
fitHeight:bind if((slider.value*maxH) &lt; h)
maxH * slider.value else h
};
var anim = TranslateTransition{
fromX:0 toX:w – maxW
node:imgView repeatCount:TranslateTransition.INDEFINITE
autoReverse:true
}
var rotateAngle = 0;
… //Address Bar Group and loadImg() function not shown
def footer = Group{
layoutX: 20
layoutY: h – 60
content:HBox {
spacing: 12
content:[
slider,
Button{text:"Rotate" action:function(){
rotateAngle = rotateAngle + 90;
imgView.rotate = rotateAngle;
}}
HBox{spacing:7 content:[
Button{text:"Reflection"
onMouseClicked:function(e){
imgView.effect =
if(imgView.effect == null or
or not (imgView.effect instanceof
Reflection))
Reflection{fraction:0.3 topOffset:0}
else null
}}
… // Other effects omitted
Button{text:"Sepia"
onMouseClicked:function(e){
imgView.effect = if(imgView.effect == null
or not (imgView.effect instanceof
SepiaTone)
)
SepiaTone{level:0.7}
else null
}}
Button{text:"Animate"
onMouseClicked:function(e){
if(not anim.running){
anim.play();
}else{
anim.stop();
}
}}
]}
]
}
}
[/code]
When the ImageView, the Slider, and the other GUI controls are added to stage, and the application is executed, it will look like what is shown in the next screenshot. In it, you can see the reflection effect applied to the image.

How it works…

In the recipe Loading and displaying images with ImageView we have seen how to use the Image API to load and display local or remote images. This recipe extends the code in that recipe to not only load the image, but also apply effects and animations to it.
As shown in the previous screenshot, this version of the image browser includes a row of GUI controls at the bottom of the screen that are used to apply different transformations and effects to the loaded image. Let’s take a closer look at how the code works:

  • Scaling the image— using an instance of the S lider control you can dynamically grow or shrink the image. To do this, we bind the properties ImageView.fitWidth and ImageView.fitHeight to Slider.value. This causes the size of the image to grow or shrink dynamically, while maintaining proper image aspect ratio. The bound expression includes logic to ensure that the image does not grow excessively large when it is scaled up as shown below:
  • [code lang=”java”]
    ImageView{
    fitWidth:bind if((slider.value*maxW) &lt; w)
    maxW * slider.value else w
    fitHeight:bind if((slider.value*maxH) &lt; h)
    maxH * slider.value else h
    };
    [/code]

  • Image rotation— the Button instance with the label “Rotate” rotates the image instance by 90 degrees with each click by setting the imgView.rotate property.
  • Image effects— the next five buttons in the code apply effects refl ected in their
    respective names. These buttons apply the Reflection, Glow, GaussianBlur , Lighting (using a PointLight effect), and SepiaTone effect s to the image (only Refl ection and Sepia are listed in the code). All buttons work in the same way:
    if the effect currently applied to the image is null or the effect is not of the desired type, then apply the desired effect, otherwise, if the effect is already being applied, turn it off. This makes the button toggle between its assigned effect.
  • Image animation—the last Button control plays the TranslateTransition instance assigned to the variable anim. The transition animation moves the image from side-to-side indefinitely until the button is pressed again to stop the animation.

See also

  • Chapter 3—Transformation, animations, and effects
  • Chapter 4—Components and skinning
  • Loading and displaying images with ImageView

Creating image effects with blending

In the previous recipe, we saw how easy it is to build an application that loads, displays, and applies effects to images. In this recipe, we are going to explore how to create new visual effects by blending two separate image sources.

Getting ready

For this recipe, you will need to be familiar with the concepts of loading and displaying images in your application using the Image API. If necessary, review the recipe Loading and displaying images with ImageView. Part of the code also uses transition animation to slide the images one on top of the other. If you need to review topics regarding animation, refer to the recipe Creating simple animation with the Transition API from Chapter 3, Transformations, Animations, and Effects. Lastly, the recipe makes use of GUI controls to capture image URLs and action buttons to apply the effects. If you are not familiar with JavaFX‘s GUI controls, review the recipe Creating a form with JavaFX controls from Chapter 4, Components and Skinning.

How to do it…

The code listing given next is abbreviated to show the essential portions that drive the application. You can get the full listing of this code from ch05/source-code/src/image/
ImageBlendDemo.fx.
[code lang=”java”]
var scene:Scene;
def w = 800; def h = 600;
def maxW = w * 0.4; def maxH = h * 0.5;
def img1 = ImageView{
translateX:10 translateY:10
preserveRatio:true
fitWidth:maxW fitHeight:maxH
}
def img2 = ImageView{
translateX:w – maxW translateY:10
preserveRatio:true
fitWidth:maxW fitHeight:maxH
}
def imgPanel = Group {content:[img1, img2]}
def anim = Timeline {
keyFrames: [
KeyFrame{time:1s
values: [
&lt;B&gt;img1&lt;/B&gt;.translateX =&gt; (w – img1.fitWidth)/2
]
}
KeyFrame{time:1s
values: [
img2.translateX =&gt; (w – img2.fitWidth)/2
]
}
]
}
// fn to load img
function loadImg(view:ImageView,url:String){
view.effect = null;
view.image = Image{
backgroundLoading:true
url:url
}
}
// controls bottom of screen
def toggleGrp = ToggleGroup{}
def controls = Group{
layoutY: h – 200
content:[
VBox{width:w spacing:12
hpos:HPos.CENTER nodeHPos:HPos.CENTER content:[
TextBox{id:"addr1" columns:60 promptText:"http://"
action:function(){
loadImg(img1,
(scene.lookup("addr1") as TextBox).text)
}}
TextBox{id:"addr2" columns:60 promptText:"http://"
action:function(){
loadImg(img2,
(scene.lookup("addr2") as TextBox).text)
}}
HBox{
content:[
RadioButton&lt;/B&gt;{text:"ADD"
toggleGroup:toggleGrp selected:true
}
… // other blending modes omitted
RadioButton&lt;/B&gt;{text:&lt;B&gt;"LIGHTEN"
toggleGroup:toggleGrp
}
]
}
HBox{
content:[
RadioButton{text:"MULTIPLY"
toggleGroup:toggleGrp
}
… //other blending modes omitted
RadioButton{text:"SRC_OVER"
toggleGroup:toggleGrp
}
]
}
Button{
text:"Blend Images"
font:Font.font("Sans Serif",
FontWeight.BOLD, 18)
effect:DropShadow{offsetX:3 offsetY:3}
onMouseClicked:function(e){
def mode = toggleGrp.selectedButton.text;
imgPanel.blendMode = BlendMode.valueOf(mode);
anim.rate = 1.0;
anim.playFromStart();
}
onMouseReleased:function(e){
anim.rate = -1.0;
anim.play();
}
}
]}
]
}
[/code]
When the Group instances imgPanel and controls are placed on the stage, and the application is executed, it produces the next screenshot. The application lets users enter the URLs of two images and select a blend mode. When the Blend Images button is pressed, the images slide to overlap each other and apply the blend effect:

How it works…

The Group class (a node itself) allows the grouping of two or more nodes to be placed on the scene graph. One of the features of the Group node is its ability to apply a blending algorithm to the group’s members. It applies its algorithm to all children in its content property when a blend mode is provided through the blendMode:BlendMode property.
In the previous sample code provided, we use Group instance imgPanel to apply blending effects to two images placed in the group. Let’s take a closer look at how the application works:

  • The images—the first thing we do in the code is to declare two instances of ImageView, img1 and img2. To ensure that the images fit in a pre-determined dimension on the screen, we set the properties fitWidth and fitHeight on the two instances. Then, we place the two images in a Group instance called imgPanel, where they will receive blending effects.
  • The image animation— to make things a little interesting, the code uses an instance of Timeline to animate the two images. The first KeyFrame instance slides img1 from the left-hand side to the middle of the screen, and the second KeyFrame instance slides img2 from the right-hand side to the middle of the screen. The two images stack up in the middle of the screen where you can see the selected blending effect applied.
  • Loading the images—when the user types the URL location of the images in the TextBox instances, with property id=”addr1″ and id=”addr2″, and presses Enter, this invokes the function loadImg(). That function loads and attaches the loaded image to instances of ImageView img1 and img2, respectively.
  • Applying the blend—Group variable controls contains two rows of RadioButton instances (not all shown in previous code). For each instance of RadioButton, the code assigns the name of a BlendMode as its text content (that is, “ADD”, “COLOR_BURN”, “MULTIPLY”, and so on). When the user clicks on the button titled Blend Image, it creates a BlendMode object using the text of the selected radio button, and applies it to the imgPanel Group containing the images, as shown:

[code lang=”java”]
def mode = toggleGrp.selectedButton.text;
imgPanel.blendMode = BlendMode.valueOf(mode);
[/code]
BlendMode.valueOf(:String) returns an instance of BlendMode based on
a String.

There’s more…

JavaFX supports a multitude of blending options. The following table shows a list of the more
interesting modes:

The BlendedMode class offers more blended modes, including RED, GREEN, BLUE, COLOR_DOGE, HARD_LIGHT, SOFT_LIGHT, SRC_ATOP, SRC_IN, SRC_OUT, and SRC_OVER.

See also

  • Chapter 3—Creating simple animation with the transition API
  • Chapter 4—Creating a form with JavaFX controls
  • Loading and displaying images with ImageView

Playing audio with MediaPlayer

Playing audio is another important aspect of any rich client platform. One of the celebrated features of JavaFX is its ability to easily playback audio content. This recipe shows you how to create code that plays back audio resources using the MediaPlayer class.

Getting ready

This recipe uses classes from the Media API located in the javafx.scene.media package. As you will see in our example, using this API you are able to load, configure, and playback audio using the classes Media and MediaPlayer. For this recipe, we will build a simple audio player to illustrate the concepts presented here. Instead of using standard GUI controls, we will use button icons loaded as images. If you are not familiar with the concept of loading images, review the recipe Loading and displaying images with ImageView in this chapter.
In this example we will use a JavaFX podcast from Oracle Technology Network TechCast series where NandiniRamani discusses JavaFX. The stream can be found at http://streaming. oracle.com/ebn/podcasts/media/8576726_Nandini_Ramani_030210.mp3.

How to do it…

The code given next has been shortened to illustrate the essential portions involved in loading and playing an audio stream. You can get the full listing of the code in this recipe from ch05/
source-code/src/media/AudioPlayerDemo.fx
[code lang=”java”]
def w = 400;
def h = 200;
var scene:Scene;
def mediaSource = "http://streaming.oracle.com/ebn/podcasts/media/
8576726_Nandini_Ramani_030210.mp3";
def player = MediaPlayer {media:Media{source:mediaSource}}
def controls = Group {
layoutX:(w-110)/2
layoutY:(h-50)/2
effect:Reflection{
fraction:0.4 bottomOpacity:0.1 topOffset:3
}
content:[
HBox{spacing:10 content:[
ImageView{id:"playCtrl"
image:Image{url:"{__DIR__}play-large.png"}
onMouseClicked:function(e:MouseEvent){
def playCtrl = e.source as ImageView;
if(not(player.status == player.PLAYING)){
playCtrl.image =
Image{url:"{__DIR__}pause-large.png"}
player.play();
}else if(player.status == player.PLAYING){
playCtrl.image =
Image{url:"{__DIR__}play-large.png"}
player.pause();
}
}
}
ImageView{id:"stopCtrl"
image:Image{url:"{__DIR__}stop-large.png"}
onMouseClicked:function(e){
def playCtrl = e.source as ImageView;
if(player.status == player.PLAYING){
playCtrl.image =
Image{url:"{__DIR__}play-large.png"}
player.stop();
}
}
}
]}
]
}
[/code]
When the variable controls is added to a scene object and the application is executed, it produces the screen shown in the following screenshot:

How it works…

The Media API is comprised of several components which, when put together, provides the mechanism to stream and playback the audio source. To playback audio requires two classes, including Media and MediaPlayer. Let’s take a look at how these classes are used to playback audio in the previous example.

  • The MediaPlayer— the first significant item in the code is the declaration and initialization of a MediaPlayer instance assigned to the variable player. To load the audio file, we assign an instance of Media to player.media. The Media class is used to specify the location of the audio. In our example, it is a URL that points to
    an MP3 file.
  • The controls—the play, pause, and stop buttons are grouped in the Group object called controls. They are made of three separate image files: play-large.
    png, pause-large.png, and stop-large.png, loaded by two instances of the ImageView class. The ImageView objects serve to display the control icons and to control the playback of the audio:
    • When the application starts, imgView displays image playlarge. png. When the user clicks on the image, it invokes its action-handler function, which firsts detects the status of the MediaPlayer instance. If it is not playing, it starts playback of the audio source by calling player.play() and replaces the playlarge.
      png with the image pause-large.png. If, however, audio is currently playing, then the audio is stopped and the image is replaced back with play-large.png.
    • The other ImageView instance loads the stop-large.png icon. When the user clicks on it, it calls its action-handler to first stop the audio playback by calling player.stop(). Then it toggles
      the image for the “play” button back to icon play-large.png.

As mentioned in the introduction, JavaFX will play the MP3 file format on any platform where the JavaFX format is supported. Anything other than MP3 must be supported natively by the OS’s media engine where the file is played back. For instance, on my Mac OS, I can play MPEG-4, because it is a supported playback format by the OS’s QuickTime engine

There’s more…

The Media class models the audio stream. It exposes properties to configure the location, resolves dimensions of the medium (if available; in the case of audio, that information is not available), and provides tracks and metadata about the resource to be played.
The MediaPlayer class itself is a controller class responsible for controlling playback of
the medium by offering control functions such as play(), pause(), and stop(). It also exposes valuable playback data including current position, volume level, and status. We will use these additional functions and properties to extend our playback capabilities in the recipe
Controlling media playback in this chapter.

See also

  • Accessing media assets
  • Loading and displaying images with ImageView

Playing video with MediaView

The previous recipe shows you how to play audio using the JavaFX Media API. This recipe builds on the versatility of the Media API and extends the previous recipe, Playing audio with MediaPlayer, and creates a video player with a few changes to the code.

Getting ready

This recipe uses classes from the Media API located in the javafx.scene.media package. As mentioned in the introduction of this recipe, the example presented here extends the code from the previous recipe to transform the audio player to now play video. We are going to reuse the same icons and the same logic to control the playback of the video. To review how to configure and use the Media API for playback, review the previous recipe Playing audio with MediaPlayer.
To illustrate video playback, the application plays back the award-winning, open-sourced, short, animated movie Big Buck Bunny. By default, the recipe will play the 854 x 480 H.264 version found at the address http://mirror.bigbuckbunny.de/peach/ bigbuckbunny_movies/big_buck_bunny_480p_h264.mov.

How to do it…

Similar to audio, playing video is simple. The abbreviated code given next highlights the portion of the code that is changed to be able to display video. You can see the full listing of the code at ch05/source-code/src/media/VideoPlayerDemo.fx.
[code lang=”java”]
def w = 800;
def h = 600;
def maxW = w * 0.8;
def maxH = h * 0.7;
var scene:Scene;
def mediaSource =
"http://mirror.bigbuckbunny.de/peach/bigbuckbunny_movies/big_buck_
bunny_480p_h264.mov";
def player = MediaView{
layoutX:(w – maxW)/2 layoutY:(h-maxH)/2
mediaPlayer:MediaPlayer {media:Media{source:mediaSource}}
fitWidth:maxW fitHeight:maxH
}
def controls = Group {
layoutX:(w-110)/2
layoutY:h-100
effect:Reflection{
fraction:0.4 bottomOpacity:0.1 topOffset:3}
content:[
HBox{spacing:10 content:[
ImageView{id:"playCtrl"
image:Image{url:"{__DIR__}play-large.png"}
onMouseClicked:function(e:MouseEvent){
def playCtrl = e.source as ImageView;
if(not(player.mediaPlayer.status ==
MediaPlayer.PLAYING)){
playCtrl.image = Image{
url:"{__DIR__}pause-large.png"
}
player.mediaPlayer.play();
}else if(player.mediaPlayer.status ==
MediaPlayer.PLAYING){
playCtrl.image = Image{
url:"{__DIR__}play-large.png"
}
player.mediaPlayer.pause();
}
}
}
ImageView{id:"stopCtrl"
image:Image{url:"{__DIR__}stop-large.png"}
onMouseClicked:function(e:MouseEvent){
def playCtrl = e.source as ImageView;
if(player.mediaPlayer.status ==
MediaPlayer.PLAYING){
playCtrl.image = Image{
url:"{__DIR__}play-large.png"
}
player.mediaPlayer.stop();
}
}
}
]}
]
}
[/code]
When the Group variable controls and the MediaView instance’s player are placed on the scene, the application will create a window as shown in the next screenshot.

How it works…

While playing audio only requires the use of the classes Media and MediaPlayer, playing video requires an additional class called the MediaView. It is of type Node and can be used to display the content of a video on the screen. Let’s take a closer look at the code:

  • The MediaView— the first major component to be initialized is the MediaView assigned to variable player. The code uses the MediaView instance to configure the dimensions and the location where the video will be rendered. In order to control playback, the code assigns the player.mediaPlayer property an instance of MediaPlayer, used to control playback. MediaPlayer is then assigned an instance of Media (through the property MediaPlayer.media) to specify the location of the video resource we want to playback.
  • The controls—the GUI controls in this example work the exact same way as described in Playing audio with MediaPlayer. We use a group of image icons to represent playback functions play, pause, and stop. When the play icon is pressed, it is starts playing the video by calling the player.mediaPlayer.play() function and toggles itself to the pause icon. When the pause icon is pressed, it pauses the video using function player.mediaPlayer.pause(). Finally, when the user presses the stop button, it makes a call to player.mediaPlayer.stop() to stop playback and toggles the play button back to the play icon.

There’s more…

Processing video is expensive. The JavaFX MediaView class supports properties which can be used to provide rendering-time hints to maximize playback performance. These Boolean properties include:

  • compositable:Boolean—if true, other nodes may overlay the MediaView node using transparency.
  • preserveRatio:Boolean—if true, the aspect ratio of the video is preserved when the node is resized through the fitWidth or fitHeight property.
  • rotatable:Boolean— when true, it allows the MediaView node to receive rotation requests through the rotate property.
  • transformable:Boolean— the node will only apply transformations through the transforms:Transform[] property when this is set to true.

See also

  • Accessing media assets
  • Playing audio with MediaPlayer

Creating a media playback component

The previous two recipes, Playing audio with MediaPlayer and Playing video with MediaView, show you how to build applications quickly to playback media sources with basic controls, such as play, pause, and stop. However, the Media API supports more functionalities than
what have been discussed so far. This recipe shows you how to build a custom media component to playback media sources providing extended functionalities such as fast forward, reverse, and timing information.

Getting ready

This recipe uses classes from the Media API located in the javafx.scene.media package.
The example presented here extends the code from the previous recipe Playing video with
MediaView to create a playback component
. The component will take advantage of the functionalities and runtime data provided by the Media API to extend the features of the video
player example. Before you continue, ensure that you are familiar with the materials covered in the recipes Playing audio with MediaPlayer and Playing video with MediaView.

How to do it…

The shortened code given next provides highlights of the more significant items involved in creating the playback component. You can access the full listing of the code from ch05/
source-code/src/media/MediaControllerComponent.fx.

  1. Let’s define class MediaController as CustomNode that encapsulates the
    playback icons/buttons and control logic:
  2. [code lang=”java”]
    class MediaController extends CustomNode{
    public var mediaPlayer:MediaPlayer;
    var timestat = bind
    "{%02d mediaPlayer.currentTime.toHours()
    mod 12 as Integer}:"
    "{%02d mediaPlayer.currentTime.toMinutes()
    mod 60 as Integer}:"
    "{%02d mediaPlayer.currentTime.toSeconds()
    mod 60 as Integer}/"
    "{%02d mediaPlayer.media.duration.toHours()
    mod 12 as Integer}:"
    "{%02d mediaPlayer.media.duration.toMinutes()
    mod 60 as Integer}:"
    "{%02d mediaPlayer.media.duration.toSeconds()
    mod 60 as Integer}";
    // image icons
    def imgReverse = Image{url:"{__DIR__}reverse-small.png"};
    def imgPlay = Image{url:"{__DIR__}play-small.png"};
    def imgPause = Image{url:"{__DIR__}pause-small.png"};
    def imgFfwd = Image{url:"{__DIR__}ffwd-small.png"};
    def imgVolup = Image{url:"{__DIR__}volup-small.png"}
    def imgVolDn = Image{url:"{__DIR__}voldown-small.png"};
    def controls = Group {
    content:[
    HBox{spacing:10 content:[
    // reverse button
    ImageView{id:"reverseCtrl" image:imgReverse
    onMousePressed:function(e:MouseEvent){
    mediaPlayer.currentTime =
    mediaPlayer.currentTime
    – (mediaPlayer.media.duration * 0.01);
    }
    }
    // play button
    ImageView{id:"playCtrl" image:imgPlay
    onMouseClicked:function(e:MouseEvent){
    … // starts media playback
    }
    }
    // fast forward
    ImageView{id:"ffwdCtrl" image:imgFfwd
    onMousePressed:function(e:MouseEvent){
    mediaPlayer.currentTime =
    mediaPlayer.currentTime
    + (mediaPlayer.media.duration * 0.01);
    }
    }
    // volume up
    ImageView{id:"voldn" image:imgVolDn;
    onMouseClicked:function(e){
    mediaPlayer.volume =
    mediaPlayer.volume – 0.4;
    }
    }
    // volume down
    ImageView{id:"volup" image:imgVolup
    onMouseClicked&lt;/B&gt;:function(e){
    mediaPlayer.volume =
    mediaPlayer.volume + 0.4;
    }
    }
    ]}
    // progress bar
    Line{
    startX:0 startY:40 endX:100 endY:40
    stroke:Color.MAROON
    }
    Circle{
    radius:5
    fill:Color.MAROON
    centerX:bind
    if(mediaPlayer.media.duration &gt; 0ms)
    (mediaPlayer.currentTime /
    mediaPlayer.media.duration)*100
    else 5
    centerY:40
    }
    Text{
    x:105 y:35
    textAlignment:TextAlignment.LEFT
    textOrigin:TextOrigin.TOP
    font:Font.font(“Sans Serif", 10)
    content: bind timestat
    }
    ]
    }
    override protected function create () : Node {
    return controls
    }
    }
    [/code]

  3. The next code segment shows you how to use the MediaController class
    defined earlier:
  4. [code lang=”java”]
    def w = 800;
    def h = 600;
    def maxW = w * 0.8;
    def maxH = h * 0.7;
    var scene:Scene;
    def mediaSource = "http://mirror.bigbuckbunny.de/peach/bigbuckbunny_
    movies/big_buck_bunny_480p_h264.mov";
    def video = MediaView{
    layoutX:(w – maxW)/2 layoutY:(h-maxH)/2
    mediaPlayer:MediaPlayer {media:Media{source:mediaSource}}
    fitWidth:maxW fitHeight:maxH
    }
    def &lt;B&gt;controls = MediaController&lt;/B&gt; {
    &lt;B&gt;mediaPlayer: video.mediaPlayer&lt;/B&gt;
    showReflection:true
    layoutX: (w – 200)/2 layoutY:video.fitHeight + 50
    }
    [/code]

When we place variable video and the instance of MediaController in a scene and execute the application, we get a screen as shown in the next screenshot:

How it works…

The custom class presented in this recipe implements a CustomNode which encapsulates the icons and logic for media playback control functions including reverse, play, fast-forward, volume up, and volume down. The class also provides visual feedback on the length and current progression of the video playback. Let’s take a closer look at the custom class:

  • Textual time progression— before we look at the control functions, we will look at how
    the component reports time progression for the playback. The first item involved in time progression feedback is the variable timestat (to which a Text object that displays progression information is bound). timestat is itself bound to several expressions that return values containing current time and total time of playback, using values from mediaPlayer.currentTime and mediaPlayer.media.duration. Since time is reported as a Duration type, we have to pluck out each time subdivision (hour, minute, seconds) individually using the mod operator. Then, each unit is formatted to be printed as zero-padded values as shown in the snippet below:
  • [code lang=”java”]
    var timestat = bind
    "{%02d mediaPlayer.currentTime.toHours()
    mod 12 as Integer}:"
    "{%02d mediaPlayer.currentTime.toMinutes()
    mod 60 as Integer}:"
    …
    [/code]

  • Visual time progression—to provide visual feedback of the progression of the playback,
    the media controller uses a custom progress bar composed of a Circle that slides along a Line instance. The line represents the total duration of the video, and the location of the circle (along the line) represents the current position of the playhead.
    To achieve this, the Circle.centerX property is bound to an expression that returns a ratio of mediaPlayer.currentTime/mediaPlayer.media.duration. This ratio is used to normalize the progress bar by multiplying it to the length of the line to get the current position of the circle, as shown in the snippet below:
  • [code lang=”java”]
    Circle{
    …
    centerX:bind
    if(mediaPlayer.media.duration &gt; 0ms)
    (mediaPlayer.currentTime /
    mediaPlayer.media.duration)*100
    else 5
    }
    [/code]

  • The controls—a s before, the control buttons consist of image icons displayed by
    instances of ImageView. The custom component loads six icons that represent functionalities such as reverse, play, pause, fast-forward, volume up, and volume down.
    The play and pause icons, assigned to ImageView instance with id = “playCtrl”, use the same logic from previous media playback recipes (consult the recipe Playing audio with MediaPlayer for details). Let’s see how the others work:
    • To fast-forward and reverse, we use ImageView instances with id=”reverseCtrl” and id=”ffwdCtrl” respectively. When the user clicks on these icons, the code adds one percent of the
      total duration to (or subtracts from) mediaPlayer.currentTime property. This has the effect of moving the playhead in the desired direction.
    • To adjust the volume is even simpler. We use instances of ImageView with id=”volup” and id=”voldn” to control the volume. When the user clicks on the icon, it sets mediaPlayer.
      volume to the desired ratio. To increase the volume we add 0.4 to the current volume. To decrease the volume, we subtract 0.4 from the current volume level.

Filed Under: Java FX Tagged With: JavaFX Media

Building an EJB 3.0 Persistence Model with Oracle JDeveloper

September 5, 2010 by itadmin Leave a Comment

EJB 3.0 Database Persistence with Oracle Fusion Middleware 11g

EJB (Enterprise JavaBeans) 3.0 entity beans is a commonly used database persistence technology. EJB 3.0 has simplified the development of EJBs with an annotations-based APithat does not require remote/local interfaces, home/local home interfaces, or deployment descriptors. Developing entity EJBs requires an application server and a relational database, and optionally a Java EE IDE to simplify the process of development. The objective of the JSR-000220 Enterprise JavaBeans 3.0 specification ( http://jcp.org/aboutJava/communityprocess/final/jsr220/index.html) is to improve the EJB architecture by reducing its complexity from the developer’s point of view. EJB 3.0 has introduced some new features, which include support for metadata annotations, default values for configuration, simplified access to environment variables, simplified session and entity beans, interceptors, enhanced support for checked
exceptions, and elimination of callback interfaces.
A number of books are available on EJB 3.0, but none cover EJB 3.0 on the Oracle Fusion Middleware (11g) platform. Most of the EJB 3.0 books are GlassFish server based, which has only 10percent of the application server market. Welcome to EJB 3.0 Database Persistence with Oracle Fusion Middleware 11g, a book that will teach you how to leverage EJB 3.0 persistence on Oracle Fusion Middleware 11g. Oracle Fusion Middleware 11g includes many components such as the SOA/BPM Suite, WebCenter, and Oracle Identity Management. All of these components run on Oracle Weblogic Server 11g. The main development tool (IDE) for Oracle Fusion Middleware is Oracle JDeveloper. In respect of EJB 3.0, JDeveloper provides wizard support to reverse engineer database tables as EJB 3.0 entity beans. JDeveloper 11g also provides a wizard for creating session beans. The JPA persistence provider used in JDeveloper 11g is the EclipseLink persistence provider. JDeveloper comes with its own embedded/integrated Weblogic Server instance, which makes it very easy to develop and test within the one
environment. We shall be using the embedded WebLogic Server 11g in some of the chapters and the standalone WebLogic Server in others.
The objective of the book is to discuss the support of EJB 3.0 database persistence in Oracle Fusion Middleware 11g. While JDeveloper is the main Java IDE used in the book, one of the chapters leverages the Oracle Enterprise Pack for Eclipse. The book covers all aspects of EJB 3.0 database persistence including:

  • Creating EJB 3.0 entity beans from database tables
  • Creating session bean façades for entity beans
  • Entity beans with session beans
  • Creating EJB 3.0 entity relationships
  • Creating JSF and ADF Faces user interfaces (UIs) on top of EJB 3.0
    database persistence
  • Using EJB 3.0 database persistence in combination with Ajax and web services

also read:

  • JPA in NetBeans 6.1
  • EJB 3.0 and WebServices
  • Introduction to Java Persistence API(JPA)
  • EJB 3.0 Timer Services – An Overview

What This Book Covers

In Chapter 1, What’s New in EJB 3.0, we discuss the new features in the EJB 3.0 specification, such as support for metadata annotations, default values for configuration, simplified session and entity beans, and enhanced support for checked exceptions.

In Chapter 2, Converting an EJB 2.0 Entity to an EJB, we convert an example EJB 2.0 entity bean to an EJB 3.0 entity bean. We also generate the session bean façade for the EJB 3.0 entity bean. XSLT transformation is used for converting the EJB 2.0 entity bean to an EJB 3.0 entity bean.

In Chapter 3, EclipseLink JPA Persistence Provider, we discuss the JPA framework and the EclipseLink persistence provider.

In Chapter 4, Building an EJB 3.0 Persistence Model with Oracle JDeveloper, we discuss EJB 3.0 database persistence with JDeveloper 11g, WebLogic Server 11g, and Oracle Database 10g. We create an EJB 3.0 entity bean from a database table, create a session bean façade, and finally create a JSP test client. Using the test client, we create, retrieve, and delete entity bean instances.
In Chapter 5, EJB 3.0 Persistence with Oracle Enterprise Pack for Eclipse, we discuss the same example we covered in Chapter 4, but with the Oracle Enterprise Pack for Eclipse, WebLogic Server, and the open source MySQL database, which has been acquired by Oracle.

In Chapter 6, EJB 3.0 with ADF Faces UI, we discuss using an ADF Faces client for EJB 3.0 database persistence. We create an entity bean using data input from an ADF Faces user interface (UI). Subsequently, we find an entity bean instance using data input from an ADF Faces UI.

In Chapter 7, Creating EJB 3.0 Entity Relationships, we discuss EJB 3.0 entity relationships using, as an example, three entity beans that have inter-relationships. We also discuss the significance of a fetch strategy.

In Chapter 8, EJB 3.0 Database Persistence with Ajax in the UI, we discuss EJB 3.0 database persistence in combination with Ajax in the user interface (UI). We demonstrate data validation and autocompletion with Ajax.

In Chapter 9, Using JSF with Entity Relationships, we discuss adding JSFs to EJB 3.0 database persistence to create and persist entity bean instances that have entity relationships between them.

In Chapter 10, Creating an EJB 3.0 Web Service, we create a JAX-WS Web Service from an EJB 3.0 entity bean, create a web service client, package and deploy the web service to WebLogic Server, and test the Web Service using the WebLogic console.

Building an EJB 3.0 Persistence Model with Oracle JDeveloper

Oracle Fusion Middleware is a family name for a set of Java EE products that are integrated for SOA and web application deployment. WebLogic Server (WLS) is the Java EE container and Oracle JDeveloper the Java EE and SOA development IDE. In this chapter, we will use JDeveloper to create an EJB 3.0 application, and then we will deploy and test our application leveraging the embedded WebLogic Server that comes with JDeveloper. This makes it very easy for us to develop, deploy, and test our application.
WebLogic server 10.x provides some value-added features to facilitate EJB 3 development. WebLogic server 10.x supports automatic deployment of a persistence unit based on the injected variable’s name. The @javax.persistence. PersistenceContext and @javax.persistence.PersistenceUnit annotation s are used to inject the persistence context in an EntityManager or EntityManagerFactory variable . A persistence context is a set of entities that are mapped to a database with a global JNDiname. If the name of the injected variable
is the same as the persistence unit, the unitName attribute of the @PersistenceContext or @PersistenceUnit is not required to be specified. The EJB container automatically deploys the persistence unit and sets its JNDiname to be the same as the persistence unit name in persistence.xml. For example, if the persistence unit name in the persistence.xml file is em, an EntityManager variable may be injected with the persistence context as follows:

[code lang=”java”]
@PeristenceContext
private EntityManager em;
[/code]

We did not need to specify the unitName attribute in the @PersistenceContext because the variable name is the same as the persistence unit. Similarly, an EntityManagerFactory variable may be injected with the persistence context as follows, emf being also the persistence unit name:

[code lang=”java”]
@PersistenceUnit
private EntityManagerFactory emf;
[/code]

Another value-added feature in WebLogic server 10.x is support for vendor-specific subinterfaces of the EntityManager interface . For example, the BEA Kodo persistence provider provides the KodoEntityManager subinterface , which may be injected with the persistence context as follows:

[code lang=”java”]
@PersistenceContext
private KodoEntityManager em;
[/code]

Setting the environment

Before getting started, we need to install Oracle JDeveloper 11g, which may be downloaded from http://www.oracle.com/technology/products/jdev/index. html. Download the Studio Edition, which is the complete version of JDevloper
with all the features. Oracle JDeveloper 11g is distributed as a GUiself-extractor application. Click on the jdevstudio11110install application. The Oracle Installer gets started. Click on Next in the Oracle Installer. Choose a middleware home directory and click on Next.

Choose the Install Type as Complete, which includes the integrated WebLogic Server, and click on Next.

Confirm the default Product Installation directories and click on Next.  The WebLogic Server installation directory is the wlserver_10.3 folder within the middleware home directory. Choose a shortcut location and click on Next. The Installation Summary lists the products that are installed, which include the WebLogic Server and the WebLogic JDBC drivers. Click on Next to install Oracle JDeveloper 11g and the integrated WebLogic Server 10.3.


We also need to install the Oracle database 10g/11g or the lightweight Oracle XE , which may be downloaded from ttp://www.oracle.com/technology/software/products/database/index.html. When installing Oracle database, also install the sample schemas.

Creating a datasource in JDeveloper

Next, we create a JDBC datasource in JDeveloper. We shall use the datasource in the EJB 3.0 entity bean for database persistence. First, we need to create a database table in some sample schema, OE for example. Run the following SQL script in SQL *Plus:

[code lang=”java”]
CREATE TABLE Catalog (id INTEGER PRIMARY KEY NOT NULL, journal
VARCHAR(100), publisher VARCHAR(100), edition VARCHAR(100), title
VARCHAR(100), author VARCHAR(100));
[/code]

A database table gets created in the OE sample schema.

Next, we need to create a JDBC connection in JDeveloper with Oracle database. Open the Database Navigator or select the Database Navigator tab if already open. Rightclick on the IDE Connections node and select New Connection.

In the Create Database Connection window, specify a Connection Name, select Connection Type as Oracle (JDBC), specify Username as OE, which is the schema in which the Catalog table is created, and specify the password for the OE schema. Select Driver as thin, Host Name as localhost, SID as ORCL, and JDBC Port as 1521. Click on the Test Connection button to test the connection. If the connection gets established, click on OK.

The OracleDBConnection gets added to the Database Navigator view. The CATALOG table that we created is listed in the Tables.

Creating an EJB 3.0 application

In this section, we create an EJB 3.0 application in JDeveloper. Select New Application.

Specify an Application Name, select the Java EE Web Application template, which consists of a Model project and a ViewController project, and click on Next.

Next, specify the name (EJB3ViewController) for the View and Controller project. In the Project Technologies tab, transfer the EJB project technology from the Available list to the Selected list using the > button. We have selected the EJB project technology, as we shall be creating an EJB 3.0 model. Click on Next.

Select the default Java settings for the View project and click on Next.

Configure the EJB Settings for the View project. Select EJB Version as Enterprise JavaBeans 3.0 and select Using Annotations. Click on Next. Next, create the Model project. Specify the Project Name (EJB3Model for example), and in the Project Technologies tab transfer the EJB project technology from the Available list to the Selected list using the > button. We have added the EJB project technology, as the
EJB 3.0 application client is created in the View project. Click on Next.


Select the default Java settings for the Model project and click on Next.

Similar to the View project, configure the EJB settings for the Model project. Select EJB Version as Enterprise JavaBeans 3.0, select Using Annotations and click on Finish. As we won’t be using a jndi.properties file or an ejb-jar.xml file , we don’t need to select the generate option for the jndi.properties file and the ejb-jar.xml file.

An EJB 3.0 application, which consists of a Model project and a ViewController project, get added in the Application tab.

Select the EJB3Model project in the Application navigator and select Tools | Project Properties. In the Project Properties window, select the Libraries and Classpath node. The EJB 3.0 library should be in the Classpath Entries.

Select the EJB Module node and select the OracleDBConnection in the Connection drop-down list. The datasource corresponding to the OracleDBConnection is jdbc/OracleDBConnectionDS.

Creating an EJB 3.0 entity bean

In this section we shall map an Oracle database table to an entity bean. Subsequently we shall discuss the components of the entity bean class.

Mapping an Oracle database table to an entity bean

In this section, we create an EJB 3.0 entity bean from the Oracle database table CATALOG that we created earlier. Select the EJB3Model project in the Application navigator and select File | New. In the New Gallery window, select Categories | Business Tier | EJB and Items | Entities from Tables, and click on OK.

In the Persistence Unit, window, select New to create a new persistence unit. In the New Persistence Unit window specify a persistence unit name (em). Specify JTA DataSource Name as jdbc/OracleDBConnectionDS, which is the datasource name corresponding to the OracleDBConnection connection. Select the default settings for Toplink: Server Platform as WebLogic 10. Click on OK.

The em Persistence Unit gets created. Click on OK in the Persistence Unit window.

Select Type of Connection as Online Database Connection and click on Next.

In the Database Connection Details window, select the OracleDBConnection and click on Next. We had configured a connection earlier, but the database connection can be created implicitly in the Database Connection Details, instead of explicitly.

In the Select Tables window, select Schema as OE, Name Filter as %, and check the Auto Query checkbox. Select the CATALOG table and click on Next.

Select the default settings in the General Options window. The default package name is model. In the Entity Class, select Place member-level annotations on as Fields, and select the Implement java.io.Serializable checkbox. Click on Next.

In the Specify Entity Details window, select Table Name as OE.CATALOG. As shown in the following screenshot, specify Entity Name as Catalog and Entity Class as model.Catalog. Click on Next.

The Summary page lists the EJB 3.0 JPA Entity that will be generated. In the Summary Page, click on Finish.

The CMP Entity bean class—model.Catalog—gets created. The persistence.xml deployment descriptor gets created in the META-INF directory.

The entity bean class

The entity bean class is just a POJO class annotated with the @Entity annotation . A @NamedQuery specifies a findAll query , which selects all the entity instances. An entity bean that has caching enabled is persisted to a database; the entity bean is serialized by caches. Therefore, the entity bean class implements the java. io.Serializable interface . Specify a serialVersionUID variable that is used by serialization runtime to associate a version number with the serializable class:

[code lang=”java”]
private static final long serialVersionUID = 7422574264557894633L;
[/code]

The database columns are mapped to entity bean properties, which are defined as private variables. The getter setter methods for the properties are also defined. The identifier property is specified with the @Id annotation. The @Column annotation specifies that the id column is not nullable:

[code lang=”java”]
@Id
@Column(nullable = false)
private long id;
[/code]

By default the id column of type INTEGER is mapped to a field of type Long. Modify the id field to type long, as usually id values are of primitive type. The entity bean class is listed next:

[code lang=”java”]
package model;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
@Entity
@NamedQueries({
@NamedQuery(name = "Catalog.findAll", query = "select o from Catalog
o")
})
public class Catalog implements Serializable {
private String author;
private String edition;
private static final long serialVersionUID = 7422574264557894633L;
@Id
@Column(nullable = false)
private long id;
private String journal;
private String publisher;
private String title;
public Catalog() {super();
}
public Catalog(String author, String edition, long id, String
journal,
String publisher, String title) {
super();
this.author = author;
this.edition = edition;
this.id = id;
this.journal = journal;
this.publisher = publisher;
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getEdition() {
return edition;
}
public void setEdition(String edition) {
this.edition = edition;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getJournal() {
return journal;
}
public void setJournal(String journal) {
this.journal = journal;
}
public String getPublisher() {
return publisher;
}
public void setPublisher(String publisher) {
this.publisher = publisher;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
[/code]

The persistence.xml file is used to define the persistence unit/s, which include a JTA datasource that is used for database persistence. The persistence provider is specified as org.eclipse.persistence.jpa.PersistenceProvider. The jtadata-source is defined as java:/app/jdbc/jdbc/OracleDBConnectionDS. The eclipselink.target-server property is specified as WebLogic_10. The javax.persistence.jtaDataSource property is specified as java:/app/jdbc/jdbc/OracleDBConnectionDS, which is just the default mapping JDeveloper uses for the JTA Data Source. The java:/app/jdbc prefix gets added to the JTA Data Source specified when creating the persistence unit. The persistence.xml configuration file is listed next:

[code lang=”java”]
<?xml version="1.0" encoding="windows-1252" ?>
<persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/
persistence_1_0.xsd"
version="1.0" xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="em">
<provider>
org.eclipse.persistence.jpa.PersistenceProvider
</provider>
<jta-data-source>
java:/app/jdbc/jdbc/OracleDBConnectionDS
</jta-data-source>
<class>
model.Catalog
</class>
<properties>
<property name="eclipselink.target-server" value="WebLogic_10"
/>
<property name="javax.persistence.jtaDataSource"
value="java:/app/jdbc/jdbc/OracleDBConnectionDS" />
</properties>
</persistence-unit>
</persistence>
[/code]

Creating EJB 3.0 a session bean

One of the best practices in, developing an entity bean is to wrap it in a session bean for a client. The entity bean is not directly accessed by a client. To create a session bean select the EJB3Model project and select File | New. In the New Gallery window, select Categories | Business Tier | EJB and Items | Session EJB. Click on OK.

Specify the EJB Name as CatalogTestSessionEJB. Select Session Type as Stateless and Transaction Type as Container. We have selected the stateless session bean because stateless session beans are less resource-intensive due to the lack of the overhead to keep the state of a unique client-bean session. Select the default mapped name (EJB3-SessionEJB). The Generate Session Façade Methods checkbox is selected by default. The Entity Implementation is JPA Entities by default. The persistence unit is em. Click on Next.

Select the default JPA Entity Methods to create and click on Next.

Specify the Bean Class (model.CatalogTestSessionEJBBean) and click on Next.

Select the EJB business interface to implement. Select the Implement a Remote Interface checkbox, specify the Remote interface (model.CatalogTestSessionEJB). Click on Next. The remote interface may be used in a distributed environment, but if using the client and the EJB 3.0 model in the same JVM, the local client view may be used.

The Summary page lists the session bean and the corresponding bean and interface classes that will be generated. In the Summary window, click on Finish.

The session bean class

A session bean class CatalogTestSessionEJBBean gets added to the entity bean model project. The remote business interface for the session bean, CatalogTestSessionEJB, also gets created.

The CatalogTestSessionEJBBean cl ass is annotated with the annotation @Stateless. The mappedName attribute specifies the global JNDifor the session bean. We shall use the mapped name in the test client to lookup the session bean and invoke method/s on it. The @Remote annotation indicates that the session bean is a remote interface.

[code lang=”java”]
@Stateless(name = "CatalogTestSessionEJB", mappedName = "EJB3-
SessionEJB")
@Remote
public class CatalogTestSessionEJBBean implements
CatalogTestSessionEJB { }
[/code]

In the session bean an EntityManager is injected using the @PersistenceContext annotation . The unitName is specified, but not required, as the EntityManager variable name is the same as the persistence unit name.

[code lang=”java”]
@PersistenceContext(unitName = "em")
private EntityManager em;
[/code]

Add a method test() to the session bean and the remote interface. In the test() method, create a Catalog entity instance with the new operator:

[code lang=”java”]
Catalog catalog =new Catalog("Kimberly Floss", "Nov-Dec 2004", new
Integer(1),"Oracle Magazine", "Oracle Publishing","Database Resource
Manager");
[/code]

Invoke the persistEntity(Object) method to persist the entity bean instance:

[code lang=”java”]
persistEntity(catalog);
[/code]

The persistEntity method invokes the persist method of the EntityManager to persist the entity bean:

[code lang=”java”]
em.persist(entity);
[/code]

Similarly, persist two more entity bean instances. Next, create an instance of the Query object using the createQuery method to run a Java Persistence Query Language statement. Bind an author name to the named parameter :name using the setParameter method, and run the Java persistence query statement using the getResultList method , which returns a List:

[code lang=”java”]
List catalogEntry =
em.createQuery("SELECT c from Catalog c where
c.author=:name").setParameter("name","Jonas Jacobi").getResultList();
[/code]

Iterate over the List, which is actually just one catalog entry, to output field values for the journal, publisher, edition, title, and author fields:

[code lang=”java”]
for (Iterator iter = catalogEntry.iterator(); iter.hasNext(); )
{Catalog element = (Catalog)iter.next();
retValue =retValue + "<br/>" + element.getJournal() +
"<br/>" + element.getPublisher() +
"<br/>" + element.getEdition() + "<br/>" +element.getTitle() + "<br/>"
+ element.getAuthor() +
"<br/>";
}
[/code]

Similarly, run a query to list all titles. Remove an entity instance using the remove method of the EntityManager. Subsequently, run a query to list all the remaining entity instances.

[code lang=”java”]
em.remove(catalog2);
[/code]

The test method returns a String, which consists of a catalog entry, a list of all the titles, and all the entity instances after removing an entity instance. The session bean class is listed next:

[code lang=”java”]
package model;
import java.util.Iterator;
import java.util.List;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
@Stateless(name = "CatalogTestSessionEJB",
mappedName = "EJB3-SessionEJB")
@Remote
public class CatalogTestSessionEJBBean implements
CatalogTestSessionEJB {
@PersistenceContext(unitName = "em")
private EntityManager em;
public CatalogTestSessionEJBBean() {
}
public String test() {
Catalog catalog =
new Catalog("Kimberly Floss", "Nov-Dec 2004", new Integer(1),
"Oracle Magazine", "Oracle Publishing",
"Database Resource Manager");
persistEntity(catalog);
Catalog catalog2 =
new Catalog("Jonas Jacobi", "Nov-Dec 2004", new Integer(2),
"Oracle Magazine", "Oracle Publishing",
"From ADF UIX to JSF");
persistEntity(catalog2);
Catalog catalog3 =
new Catalog("Steve Muench", "March-April 2005", new Integer(3),
"Oracle Magazine", "Oracle Publishing",
"Starting with Oracle ADF");
persistEntity(catalog3);
String retValue = "<b>A catalog entry: </b>";
List catalogEntry =
em.createQuery("SELECT c from Catalog c where c.author=:name").
setParameter("name", "Jonas Jacobi").getResultList();
for (Iterator iter = catalogEntry.iterator(); iter.hasNext(); ) {
Catalog element = (Catalog)iter.next();
retValue = retValue + "<br/>" + element.getJournal() + "<br/>" +
element.getPublisher() + "<br/>" +
element.getEdition() + "<br/>" +
element.getTitle() + "<br/>" + element.getAuthor() +
"<br/>";
}
retValue = retValue + "<b>All Titles: </b>";
List allTitles =
em.createQuery("SELECT c from Catalog c").getResultList();
for (Iterator iter = allTitles.iterator(); iter.hasNext(); ) {
Catalog element = (Catalog)iter.next();
retValue = retValue + "<br/>" + element.getTitle() + "<br/>";
}
em.remove(catalog2);
retValue = retValue + "<b>All Entries after removing an entry:
</b>";
List allCatalogEntries =
em.createQuery("SELECT c from Catalog c").getResultList();
for (Iterator iter = allCatalogEntries.iterator(); iter.hasNext(); )
{
Catalog element = (Catalog)iter.next();
retValue = retValue + "<br/>" + element + "<br/>";
}
<b>return</b> retValue;
}
public Object mergeEntity(Object entity) {
return em.merge(entity);
}
public Object persistEntity(Object entity) {
em.persist(entity);
return entity;
}
/** <code>select o from Catalog o</code> */
public List<Catalog> queryCatalogFindAll() {
return em.createNamedQuery("Catalog.findAll").getResultList();
}
/** <code>select o from Catalog o</code> */
public List<Catalog> queryCatalogFindAllByRange(int firstResult,
int maxResults) {
Query query = em.createNamedQuery("Catalog.findAll");
if (firstResult > 0) {
query = query.setFirstResult(firstResult);
}
if (maxResults > 0) {
query = query.setMaxResults(maxResults);
}
return query.getResultList();
}
public void removeCatalog(Catalog catalog) {
catalog = em.find(Catalog.class, catalog.getId());
em.remove(catalog);
}
}
[/code]

The remote business interface is listed next:

[code lang=”java”]
package model;
import java.util.List;
import javax.ejb.Remote;
@Remote
public interface CatalogTestSessionEJB {
List<Catalog> queryCatalogFindAll();
String test();
List<Catalog> queryCatalogFindAllByRange(int firstResult,
int maxResults);
void removeCatalog(Catalog catalog);
}
[/code]

Creating and testing a test client

In this section, we create a JSP client to test the entity bean using a wrapper session bean.

Creating a client

First, we need to create a JSP. Select the EJB3ViewController project and select File>New. In the New Gallery window, select Categories | Web Tier | JSP and Items | JSP. Click on OK.

In the Create JSP window, specify a FileName (EJB3Client) and click on OK.

As we shall be invoking the entity bean, which is in the model project, from the JSP, which is in the ViewController project, we need to add a dependency in the ViewController project on the Model project. Select Tools | Project Properties and select Dependencies. Click on the Edit Dependencies button.

In the Edit Dependencies window, select EJB3Model | Build Output and click on OK, as shown:

The EJB3Model project gets added to the Dependencies. Click on OK, as shown next:

In the JSP client, we look up the session bean and invoke the test() method on it, which returns a String. First, we create an InitialContext:

[code lang=”java”]
InitialContext context = new InitialContext();
[/code]

Two methods are available to look up a session bean using the remote business interface.

  • Look up the session bean remote interface using the mapped name. The global JNDiname for a session bean remote business interface is derived from the remote business interface name. The format of the global JNDI name is mappedName#qualified_name_of_businessInterface.
  • Specify the business interface JNDiname in the weblogic-ejb-jar.xml deployment descriptor. The global JNDiname is specified as follows:
    [code lang=”java”]
    <weblogic-enterprise-bean>
    <ejb-name>CatalogTestSessionEJBBean</ejb-name>
    <stateless-session-descriptor>
    <business-interface-jndi-name-map>
    <business-remote>CatalogTestSessionEJB
    </business-remote>
    <jndi-name>EJB3-SessionEJB</jndi-name>
    </business-interface-jndi-name-map>
    </stateless-session-descriptor>
    </weblogic-enterprise-bean>
    [/code]

We shall use the first method. Create a remote business interface instance using lookup with the mapped name:

[code lang=”java”]
CatalogTestSessionEJB beanRemote = (CatalogTestSessionEJB) context.
lookup("EJB3-SessionEJB#model.CatalogTestSessionEJB");
[/code]

Invoke the test() method of the session bean:

[code lang=”java”]
String catalog=beanRemote.test();
[/code]

Output the string returned by the test method:

[code lang=”java”]
<%=catalog %>
[/code]

The EJB3Client is listed next:

[code lang=”java”]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<%@ page import="model.*, javax.naming.*" %>
<%@ page
contentType="text/html;charset=windows-1252"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;
charset=windows-1252" />
<title>EJB3Client</title>
</head>
<body><% InitialContext context = new InitialContext();
CatalogTestSessionEJB beanRemote = (CatalogTestSessionEJB)
context.lookup("EJB3-SessionEJB#model.CatalogTestSessionEJB");
String catalog=beanRemote.test(); %><%=catalog %></body>
</html>
[/code]

Testing the client

To run the test client, right-click on, EJB3Client.jsp and select Run.  The output from the test client lists a catalog entry, all the titles, and all the entity instances after removing a catalog entry.

Summary

In this section, we created an EJB 3.0 entity bean in JDeveloper 11g from an Oracle database table. The Catalog entity bean is automatically created a database table CATALOG; the database table columns are mapped to entity bean properties. We created a wrapper session bean for the entity bean, including a remote business interface. We added a test method to the session bean for creating and persisting entity instances, querying entity instances, and removing an entity instance. We created a JSP test client to test the entity bean. We look up the session bean remote interface using the mapped name for the session bean and invoke the test method on the remote interface instance. In the next chapter, we shall discuss EJB 3.0 database persistence with Oracle Enterprise Pack for Eclipse and WebLogic server.

also read:

  • JPA in NetBeans 6.1
  • EJB 3.0 and WebServices
  • Introduction to Java Persistence API(JPA)
  • EJB 3.0 Timer Services – An Overview

Filed Under: Java EE Tagged With: EJB, EJB 3

Developing a Web Service with CXF

July 23, 2010 by itadmin Leave a Comment

Apache CXF Web Service Development

Apache CXF is an open source services framework that makes web service development easy, simplified, and standard based. CXF provides many features such as frontend programming, support for different transports and data bindings, support for different protocols, and other advanced concepts like Features and Invokers. It also provides a programming model to build and deploy RESTful services.

also read:

  • What is UDDI?
  • Apache Axis 2 Web Services
  • RESTFul Java Web Services

The focus of the book is to provide readers with comprehensive details on how to use the overview of CXF features and architecture. Each feature is explained in a separate chapter, each of which covers well defined practical illustrations using real world examples. This helps developers to easily understand the CXF API. Each chapter provides hands on examples and provides step-by-step instructions to develop, deploy, and execute the code.

What This Book Covers

The book is about the CXF service development framework. The book covers two of the most widely used approaches, for web services development, SOAP and REST. Each chapter in the book provides hands on examples, where we look in detail at how to use the various CXF features in detail to develop web services in a step-by-step fashion Chapter 1: Getting Familiar with CXF revisits web service concepts and provides an introduction to CXF framework and its usage, and prepares the CXF environment for the following chapters. By the end of this chapter the reader will be able to understand the core concepts of CXF.
Chapter 2: Developing a Web Service with CXF focuses on getting the reader quickly started with the CXF framework by developing a simple web service and running it under the Tomcat container. By the end of this chapter the reader will be able to develop a simple web service using CXF.
Chapter 3: Working with CXF Frontends illustrates the use of different frontends, like JAX-WS and CXF simple fronted API, and shows how to apply code-first and contractfirst development approaches for developing web services. We will look at how to create dynamic web service clients, the use of web service context, and how to work directly with XML messages using CXF Provide and Dispatch implementation. By the end of this chapter the reader will be able to apply different frontends to develop a web service.
Chapter 4: Learning about Service Transports explains basic transport protocols for a service and shows you how to configure HTTP, HTTP(s), JMS, and Local protocol for web services communication. You will get introduced to the concept of HTTP conduit, which enables the client program to apply policies or properties to HTTP and HTTPs protocols, and how to generate a crypto key and a key store for HTTPs based service communication. You will learn how to use JMS protocol for web services communication and how to facilitate web services message exchange using CXF Local service transport.
By the end of this chapter the reader will be able develop services with different transports Chapter 5: Implementing Advanced Features will explain advanced concepts using CXF Features, Interceptors, and Invokers, and how to integrate these concepts in existing applications.
By the end of this chapter the reader will be able develop services with features like Interceptors and Invokers
Chapter 6: Developing RESTful Services with CXF explains the concept of REST demonstrates additional features for developing enterprise RESTful services. We will look at how to design, develop, and unit test the RESTful Service by taking a real world example using CXF JAX-RS implementation.
By the end of this chapter the reader will be able to design, develop, and unit test the RESTful service
Chapter 7: Deploying RESTful Services with CXF will explain how to deploy REST services in a container like Tomcat using Spring configuration, and how to test out the various operations exposed by the RESTFul application using CXF RESTful client APiusing a web service development tool. We will look at how to enable exception handling, JSON message support, and logging support for RESTful applications using CXF framework.
By the end of this chapter the reader would be able utilize various CXF features for developing RESTful services and how to leverage Spring configuration for deploying RESTful service in the tomcat container.
Chapter 8: Working with CXF Tools will explain some of the commonly used CXF tools that assist us in web services development. We will look at how to invoke a real world .NET service over the internet using a Java client and JavaScript, create web service implementation from WSDL files, generate WSDL files from web service implementation, and validate the WSDL file for compliance.
By the end of this chapter the reader will be able to use different CXF tools to develop a service.
Appendix A deals with how to set up the CXF environment, provides details on how the source code for each chapter is organized, and shows how to run the source code examples using the ANT tool and Maven Tool.
Appendix B provides an explanation of the basics of the Spring framework and IoC concepts, along with an end-to-end example which utilizes Spring IoC concepts.
By the end of this Appendix chapter the reader will have a good understanding of Spring capabilities used in the context of CXF web services development in this book.

Developing a Web Service with CXF

The first chapter provided an introduction to web services and CXF framework. We looked at the features supported by the CXF framework and how to set up the CXF environment. This chapter will focus on programming web service with CXF. CXF provides a robust programming model that offers simple and convenient APIs for web service development. The chapter will focus on illustrating a simple web service development using CXF and Spring-based configurations. The chapter will also talk about the architecture of CXF.
Before we examine CXF-based web service development, we will review the example application that will be illustrated throughout the book. The example application will be called Order Processing Application. The book will demonstrate the same application to communicate different concepts and features of CXF so that the reader can have a better understanding of CXF as a whole. This chapter will focus on the following topics:


  • Overview of a sample Order Processing Application

  • CXF-based web service development with Spring

  • Insight into CXF architecture

The Order Processing Application

The objective of the Order Processing Application is to process a customer order. The order process functionality will generate the customer order, thereby making the order valid and approved. A typical scenario will be a customer making an order request to buy a particular item. The purchase department will receive the order request from the customer and prepare a formal purchase order. The purchase order will hold the details of the customer, the name of the item to be purchased, the quantity, and the price. Once the order is prepared, it will be sent to the Order Processing department for the necessary approval. If the order is valid and
approved, then the department will generate the unique order ID and send it back to the Purchase department. The Purchase department will communicate the order ID back to the customer.

For simplicity, we will look at the following use cases:


  • Prepare an order

  • Process the order


The client application will prepare an order and send it to the server application through a business method call. The server application will contain a web service that will process the order and generate a unique order ID. The generation of the unique order ID will signify order approval.

In real world applications a unique order ID is always accompanied by the date the order was approved. However, in this example we chose to keep it simple by only generating order ID.

Developing a service

Let’s look specifically at how to create an Order Processing Web Service and then register it as a Spring bean using a JAX-WS frontend.

In Chapter 3 you will learn about the JAX-WS frontend. The chapter will also cover a brief discussion on JAX-WS. The Sun-based JAX-WS specification can be found at the following URL: http://jcp.org/aboutJava/communityprocess/final/jsr224/index.html

JAX-WS frontend offers two ways of developing a web service—Code-first and Contract-first. We will use the Code-first approach, that is, we will first create a Java class and convert this into a web service component. The first set of tasks will be to create server-side components.

In web service terminology, Code-first is termed as the Bottoms Up approach, and Contract-first is referred to as the Top Down approach.

To achieve this, we typically perform the following steps:


  • Create a Service Endpoint Interface (SEI) and define a business method to be used with the web service.

  • Create the implementation class and annotate it as a web service.

  • Create beans.xml and define the service class as a Spring bean using a JAX-WS frontend.

Creating a Service Endpoint Interface (SEI)

Let’s first create the SEifor our Order Processing Application. We will name our
SEiOrderProcess. The following code illustrates the OrderProcess SEI:
[code lang=”java”]
package demo.order;
import javax.jws.WebService;
@WebService
public interface OrderProcess {
@WebMethod
}
[/code]
As you can see from the preceding code, we created a Service Endpoint Interface named OrderProcess. The SEiis just like any other Java interface. It defines an abstract business method processOrder. The method takes an Order bean as a parameter and returns an order ID String value. The goal of the processOrder method is to process the order placed by the customer and return the unique order ID. One significant thing to observe is the @WebService annotation. The annotation is placed right above the interface definition. It signifies that this interface is not an ordinary interface but a web service interface. This interface is known as Service Endpoint Interface and will have a business method exposed as a service method to be invoked by the client.
The @WebService annotation is part of the JAX-WS annotation library. JAX-WS provides a library of annotations to turn Plain Old Java classes into web services and specifies detailed mapping from a service defined in WSDL to the Java classes that will implement that service. The javax.jws.WebService annotation also comes with attributes that completely define a web service. For the moment we will ignore these attributes and proceed with our development. The javax.jws.@WebMethod annotation is optional and is used for customizing the web service operation. The @WebMethod annotation provides the operation name and the action elements which are used to customize the name attribute of the operation and the SOAP action element in the WSDL document.
The following code shows the Order class:
[code lang=”java”]
package demo.order;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "Order")
public class Order {
private String customerID;
private String itemID;
private int qty;
private double price;
// Contructor
public Order() {
}
public String getCustomerID() {
return customerID;
}
public void setCustomerID(String customerID) {
this.customerID = customerID;
}
public String getItemID() {
return itemID;
}
public void setItemID(String itemID) {
this.itemID = itemID;
}
public int getQty() {
return qty;
}
public void setQty(int qty) {
this.qty = qty;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
[/code]
As you can see, we have added an @XmlRootElement annotation to the Order class. The @XmlRootElement is part of the Java Architecture for XML Binding (JAXB) annotation library. JAXB provides data binding capabilities by providing a convenient way to map XML schema to a representation in Java code. The JAXB shields the conversion of XML schema messages in SOAP messages to Java code without having the developers know about XML and SOAP parsing. CXF uses JAXB as the default data binding component.
The @XmlRootElement annotations associated with Order class map the Order class to the XML root element. The attributes contained within the Order object by default are mapped to @XmlElement. The @XmlElement annotations are used to define elements within the XML. The @XmlRootElement and @XmlElement annotations allow you to customize the namespace and name of the XML element. If no customizations are provided, then the JAXB runtime by default would use the same name of attribute for the XML element. CXF handles this mapping of Java objects to XML.

Developing a service implementation class


We will now develop the implementation class that will realize our OrderProcess SEI. We will name this implementation class OrderProcessImpl. The following code illustrates the service implementation class OrderProcessImpl:
[code lang=”java”]
@WebService
public class OrderProcessImpl implements OrderProcess {
public String processOrder(Order order) {
String orderID = validate(order);
return orderID;
}
/**
* Validates the order and returns the order ID
**/
private String validate(Order order) {
String custID = order.getCustomerID();
String itemID = order.getItemID();
int qty = order.getQty();
double price = order.getPrice();
if (custID != null && itemID != null && !custID.equals("")
&& !itemID.equals("") && qty > 0
&& price > 0.0) {
return "ORD1234";
}
return null;
}
}
[/code]
As we can see from the preceding code, our implementation class OrderProcessImpl is pretty straightforward. It also has @WebService annotation defined above the class declaration. The class OrderProcessImpl implements OrderProcess SEI. The class implements the processOrder method. The processOrder method checks for the validity of the order by invoking the validate
method. The validate method checks whether the Order bean has all the relevant properties valid and not null.

It is recommended that developers explicitly implement OrderProcess
SEI, though it may not be necessary. This can minimize coding errors
by ensuring that the methods are implemented as defined.

Next we will look at how to publish the OrderProcess JAX-WS web service using Spring configuration.

Spring-based server bean


What makes CXF the obvious choice as a web service framework is its use of Spring-based configuration files to publish web service endpoints. It is the use of such configuration files that makes the development of web service convenient and easy with CXF.

Please refer to the Getting Started with Spring framework appendix chapter
to understand the concept of Inversion of Control, AOP (Aspect oriented
program)
, and features provided by the Spring framework using a sample
use case.

Spring provides a lightweight container which works on the concept of Inversion of Control (IoC) or Dependency Injection (DI) architecture; it does so through the implementation of a configuration file that defines Java beans and its dependencies. By using Spring you can abstract and wire all the class dependencies in a single configuration file. The configuration file is often referred to as an Application Context or Bean Context file. We will create a server side Spring-based configuration file and name it as beans.xml. The following code illustrates the beans.xml configuration file:
[code lang=”xml”]
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<jaxws:endpoint
id="orderProcess"
implementor="demo.order.OrderProcessImpl"
address="/OrderProcess" />
</beans>
[/code]
Let’s examine the previous code and understand what it really means. It first defines the necessary namespaces. It then defines a series of <import> statements. It imports cxf.xml, cxf-extension-soap.xml, and cxf-servlet.xml. These files are Springbased configuration files that define core components of CXF. They are used to kick start CXF runtime and load the necessary infrastructure objects such as WSDL manager, conduit manager, destination factory manager, and so on The <jaxws:endpoint> element in the beans.xml file specifies the OrderProcess web service as a JAX-WS endpoint. The element is defined with the following
three attributes:


  • id—s pecifies a unique identifier for a bean. In this case, jaxws:endpoint is a bean, and the id name is orderProcess.

  • implementor— specifies the actual web service implementation class. In this case, our implementor class is OrderProcessImpl.

  • address— specifies the URL address where the endpoint is to be published. The URL address must to be relative to the web context. For our example, the endpoint will be published using the relative path /OrderProcess.


The <jaxws:endpoint> element signifies that the CXF internally uses JAX-WS frontend to publish the web service. This element definition provides a short and convenient way to publish a web service. A developer need not have to write any Java class to publish a web service.

Developing a client


In the previous section we discussed and illustrated how to develop and publish a web service. We now have the server-side code that publishes our OrderProcess web service. The next set of tasks will be to create the client-side code that will consume or invoke our OrderProcess web service. To achieve this, we will perform the following steps:

  • Develop the client-beans.xml to define the client factory class as a Spring bean using JAX-WS frontend

  • Develop a client Java application to invoke the web service


Developing a Spring-based client bean


We will create a client-side Spring-based configuration file and name it as client-beans.xml. The following code illustrates the client-beans.xml
configuration file:
[code lang=”xml”]
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<jaxws:client id="orderClient" serviceClass=
"demo.order.OrderProcess" address=
"http://localhost:8080/orderapp/OrderProcess" />
</beans>
[/code]
The <jaxws:client> element in the client-beans.xml file specifies the client bean using JAX-WS frontend. The element is defined with the following three attributes:

  • id—specifies a unique identifier for a bean. In this case, jaxws:client is a bean and the id name is orderClient. The bean will represent an SEI.

  • serviceClass—specifies the web service SEI. In this case our SEiclass is OrderProcess

  • address—specifies the URL address where the endpoint is published. In this case the endpoint is published at the URL address: http://localhost:8080/orderapp/OrderProcess


<jaxws:client> signifies the client bean that represents an OrderProcess SEI. The client application will make use of this SEito invoke the web service. Again, CXF internally uses JAX-WS frontend to define this client-side component.

Developing web service client code


We will now create a standalone Java class to invoke our OrderProcess web service. The following code illustrates the client invocation of a web service method:
[code lang=”java”]
public final class Client {
public Client() {
}
public static void main(String args[]) throws Exception {
// START SNIPPET: client
ClassPathXmlApplicationContext context
= new ClassPathXmlApplicationContext(new String[]
{"demo/order/client/client-beans.xml"});
OrderProcess client = (OrderProcess) context.
getBean("orderClient");
// Populate the Order bean
Order order = new Order();
order.setCustomerID("C001");
order.setItemID("I001");
order.setQty(100);
order.setPrice(200.00);
String orderID = client.processOrder(order);
String message = (orderID == null) ?
"Order not approved" : "Order approved;
order ID is " + orderID;
System.out.println(message);
System.exit(0);
[/code]
As you can see from the above code, we have the main method that first loads the client-beans.xml configuration file. It uses the Spring application context component ClassPathXmlApplicationContext to load the configuration file. The context component’s getBean method is passed the bean ID orderClient. This method will return the OrderProcess SEicomponent. Using the SEI, we then invoke the web service method processOrder. One thing to observe here is that the client always uses the interface to invoke a web service method. The processOrder method takes the Order bean as a parameter. The following code depicts the Order bean:
[code lang=”java”]
public class Order {
private String customerID;
private String itemID;
private int qty;
private double price;
// Contructor
public Order() {
}
// Getter and setter methods for the above declared properties
}
[/code]
The above Order bean is populated with the valid values and passed to the processOrder method. The method will then process the order and return the unique order ID. We have now finished developing server and client side components. To summarize, we created the OrderProcess service endpoint interface and the implementation class. We then created server and client-side Spring-based configuration files and finally we created the client application. The relevant components are developed and we are all set to run or execute our code. But before we do that, you will have to create one final component that will integrate Spring and CXF. We need to wire Spring and CXF through web.xml. The following code illustrates the web.xml file:
[code lang=”xml”]
<web-app>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/beans.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>CXFServlet</servlet-name>
<display-name>CXF Servlet</display-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
[/code]
Let’s go through the above piece of code. The web.xml, as we know, is the web application configuration file that defines a servlet and its properties. The file defines CXFServlet, which acts as a front runner component that initiates the CXF environment. It defines the listener class ContextLoaderListener, which is responsible for loading the server-side configuration file beans.xml. So upon the web server startup, the order process web service endpoint will be registered and published.

Running the program

The source code and build file for the chapter is available in the
Chapter2/orderapp folder of the downloaded source code.

Before running the program, we will organize the code so far developed in the appropriate folder structure. You can create the folder structure, as shown in the following screenshot, and put the components in the respective sub folders

The developed code will go into the following:


  • The Java code will go into the respective package folders

  • The beans.xml and web.xml will go into the webapp\WEB-INF folder

  • The client-beans.xml file will go into the demo\order\client folder


Once the code is organized, we will go about building and deploying it in the Tomcat server. It will typically involve three steps:

  • Building the code

  • Deploying the code

  • Executing the code


Building the code


Building the code means compiling the source Java code. We will use the ANT tool to do this. The ANT file is provided in Chapter2\orderapp folder. The following code illustrates the sample build.xml build script:
[code lang=”xml”]
<?xml version="1.0" encoding="UTF-8"?>
<project name="CXF Chapter2 example" default="build" basedir=".">
<import file="common_build.xml"/>
<target name="client" description=
"run demo client" depends="build">
<property name="param" value=""/>
<cxfrun classname="demo.order.client.Client" />
</target>
<target name="server" description=
"run demo server" depends="build">
<cxfrun classname="demo.spring.servlet.Server"/>
</target>
<property name="cxf.war.file.name" value="orderapp"/>
<target name="war" depends="build">
<cxfwar filename="${cxf.war.file.name}.war" webxml=
"webapp/WEB-INF/web.xml" />
</target>
</project>
[/code]
Alongside build.xml, you will also find common_build.xml in the same folder. The common_buid.xml refers to CATALINA_HOME environment variable to find location of tomcat installation. Please make sure that you have set up the environment variables as mentioned in Appendix A. Open the command prompt window, go to C:\orderapp folder and run the ant command. It will build the code and put the class files under the newly created build folder. The following figure shows the output generated upon running the ant command.

Deploying the code


Having built the code, we will deploy it. Deployment effectively means building and moving the code archive to the server deploy path. We will be using the Tomcat web container to deploy and run the application. To deploy our built code, navigate to project root folder, and enter the following command:
[code]ant deploy[/code]
This will build the WAR file and put it under the Tomcat server webapp path. For example, if you have installed the Tomcat under the root folder, then the WAR will be deployed to /Tomcat/webapp folder.

Executing the code


Following code deployment, we are all set to run the Order Process Application. You will execute the Java client program Client.java to invoke the Order Process web service. The program will invoke the processOrder method that will generate the order ID if the specified order is approved. Before running the client program, we need to start the Tomcat web server. There are several ways of starting the Tomcat server depending on the Tomcat version that is installed. Once the server is started, you need to run the client program by giving the following command at the command prompt window:
[code]ant client[/code]
As you can see above, we are using Ant to run the client program. Upon executing
this command, it will generate the following output:

Thus we have successfully executed the order processing web service.

CXF architecture

The architecture of CXF is built upon the following components:


  • Bus

  • Frontend

  • Messaging and Interceptors

  • Service Model

  • Data bindings

  • Protocol bindings

  • Transport


The following figure shows the overall architecture:

Bus

Bus is the backbone of the CXF architecture. The CXF bus is comprised of a Spring-based configuration file, namely, cxf.xml which is loaded upon servlet initialization through SpringBusFactory. It defines a common context for all the endpoints. It wires all the runtime infrastructure components and provides a common application context. The SpringBusFactory scans and loads the relevant configuration files in the META-INF/cxf directory placed in the classpath and accordingly builds the application context. It builds the application context from the following files:


  • META-INF/cxf/cxf.xml

  • META-INF/cxf/cxf-extension.xml

  • META-INF/cxf/cxf-property-editors.xml


The XML file is part of the installation bundle’s core CXF library JAR. Now, we know that CXF internally uses Spring for its configuration. The following XML fragment shows the bus definition in the cxf.xml file.
[code lang=”xml”]
<bean id="cxf" class="org.apache.cxf.bus.CXFBusImpl" />
[/code]
The core bus component is CXFBusImpl . The class acts more as an interceptor provider for incoming and outgoing requests to a web service endpoint. These interceptors, once defined, are available to all the endpoints in that context. The cxf.xml file also defines other infrastructure components such as BindingFactoryManager, ConduitFactoryManager, and so on. These components are made available as bus extensions. One can access these infrastructure objects using the getExtension method. These infrastructure components are registered so as to get and update various service endpoint level parameters such as service binding, transport protocol, conduits, and so on.
CXF bus architecture can be overridden, but one must apply caution when overriding the default bus behavior. Since the bus is the core component that loads the CXF runtime, many shared objects are also loaded as part of this runtime. You want to make sure that these objects are loaded when overriding the existing bus implementation.
You can extend the default bus to include your own custom components or service objects such as factory managers. You can also add interceptors to the bus bean. These interceptors defined at the bus level are available to all the endpoints. The following code shows how to create a custom bus:
[code lang=”java”]
SpringBeanFactory.createBus("mycxf.xml")
[/code]
SpringBeanFactory class is used to create a bus. You can complement or overwrite the bean definitions that the original cxf.xml file would use. For the CXF to load the mycxf.xml file, it has to be in the classpath or you can use a factory method to load the file. The following code illustrates the use of interceptors at the bus level:
[code lang=”xml”]
<bean id="cxf" class="org.apache.cxf.bus.spring.SpringBusImpl">
<property name="outInterceptors">
<list>
<ref bean="myLoggingInterceptor"/>
</list>
</property>
</bean>
<bean id="myLogHandler" class="org.mycompany.com.cxf.logging.
LoggingInterceptor">
…
</bean>
[/code]
The preceding bus definition adds the logging interceptor that will perform logging
for all outgoing messages.

Frontend

CXF provides the concept of frontend modeling, which lets you create web services using different frontend APIs. The APIs let you create a web service using simple factory beans and JAX-WS implementation. It also lets you create dynamic web service clients. The primary frontend supported by CXF is JAX-WS. We will look at how to use the Frontend programming model in the next chapter.

JAX-WS

JAX-WS is a specification that establishes the semantics to develop, publish, and consume web services. JAX-WS simplifies web service development. It defines Java-based APIs that ease the development and deployment of web services.
The specification supports WS-Basic Profile 1.1 that addresses web service interoperability. It effectively means a web service can be invoked or consumed by a client written in any language. JAX-WS also defines standards such as JAXB and SAAJ. CXF provides support for complete JAX-WS stack.
JAXB provides data binding capabilities by providing a convenient way to map XML schema to a representation in Java code. The JAXB shields the conversion of XML schema messages in SOAP messages to Java code without the developers seeing XML and SOAP parsing. JAXB specification defines the binding between Java and XML Schema. SAAJ provides a standard way of dealing with XML attachments contained in a SOAP message.
JAX-WS also speeds up web service development by providing a library of annotations to turn Plain Old Java classes into web services and specifies a detailed mapping from a service defined in WSDL to the Java classes that will implement that service. Any complex types defined in WSDL are mapped into Java classes following the mapping defined by the JAXB specification.
As discussed earlier, two approaches for web service development exist: Code-First and Contract-First. With JAX-WS, you can perform web service development using one of the said approaches, depending on the nature of the application.
With the Code-first approach, you start by developing a Java class and interface and annotating the same as a web service. The approach is particularly useful where Java implementations are already available and you need to expose implementations as services.
You typically create a Service Endpoint Interface (SEI) that defines the service methods and the implementation class that implements the SEimethods. The consumer of a web service uses SEito invoke the service functions. The SEidirectly corresponds to a wsdl:portType element. The methods defined by SEicorrespond
to the wsdl:operation element.
[code lang=”java”]
@WebService
public interface OrderProcess {
String processOrder(Order order);
}
[/code]
JAX-WS makes use of annotations to convert an SEior a Java class to a web service. In the above example, the @WebService annotation defined above the interface declaration signifies an interface as a web service interface or Service Endpoint Interface.
In the Contract-first approach, you start with the existing WSDL contract, and generate Java class to implement the service. The advantage is that you are sure about what to expose as a service since you define the appropriate WSDL Contract-first. Again the contract definitions can be made consistent with respect to data types so that it can be easily converted in Java objects without any portability issue. In Chapter 3 we will look at how to develop web services using both these approaches.
WSDL contains different elements that can be directly mapped to a Java class that implements the service. For example, the wsdl:portType element is directly mapped to SEI, type elements are mapped to Java class types through the use of Java Architecture of XML Binding (JAXB), and the wsdl:service element is mapped to a Java class that is used by a consumer to access the web service. The WSDL2Java tool can be used to generate a web service from WSDL. It has various options to generate SEiand the implementation web service class. As a developer,
you need to provide the method implementation for the generated class. If the WSDL includes custom XML Schema types, then the same is converted into its equivalent Java class.

In Chapter 8 you will learn about CXF tools. The chapter will also cover a
brief discussion on the wsdl2java tool.

Simple frontend


Apart from JAX-WS frontend, CXF also supports what is known as ‘simple frontend’. The simple frontend provides simple components or Java classes that use reflection to build and publish web services. It is simple because we do not use any annotation to create web services. In JAX-WS, we have to annotate a Java class to denote it as a web service and use tools to convert between a Java object and WSDL. The simple frontend uses factory components to create a service and the client. It does so by using Java refl ection API. In Chapter 3 we will look at how to develop simple frontend web services
The following code shows a web service created using simple frontend:
[code lang=”java”]
// Build and publish the service
OrderProcessImpl orderProcessImpl = new OrderProcessImpl();
ServerFactoryBean svrFactory = new ServerFactoryBean();
svrFactory.setServiceClass(OrderProcess.class);
svrFactory.setAddress("http://localhost:8080/OrderProcess");
svrFactory.setServiceBean(orderProcessImpl);
svrFactory.create();
[/code]

Messaging and Interceptors

One of the important elements of CXF architecture is the Interceptor components. Interceptors are components that intercept the messages exchanged or passed between web service clients and server components. In CXF, this is implemented through the concept of Interceptor chains. The concept of Interceptor chaining is the core functionality of CXF runtime.
The interceptors act on the messages which are sent and received from the web service and are processed in chains. Each interceptor in a chain is configurable, and the user has the ability to control its execution.

The core of the framework is the Interceptor interface. It defines two abstract methods—handleMessage and handleFault. Each of the methods takes the object of type Message as a parameter. A developer implements the handleMessage to process or act upon the message. The handleFault method is implemented to handle the error condition. Interceptors are usually processed in chains with every interceptor in the chain performing some processing on the message in sequence, and the chain moves forward. Whenever an error condition arises, a handleFault method is invoked on each interceptor, and the chain unwinds or moves backwards.
Interceptors are often organized or grouped into phases. Interceptors providing common functionality can be grouped into one phase. Each phase performs specific message processing. Each phase is then added to the interceptor chain. The chain, therefore, is a list of ordered interceptor phases. The chain can be created for both inbound and outbound messages. A typical web service endpoint will have three interceptor chains:


  • Inbound messages chain

  • Outbound messages chain

  • Error messages chain


There are built-in interceptors such as logging, security, and so on, and the developers can also choose to create custom interceptors.

In Chapter 5 we will learn about working with CXF advanced features.
The chapter will mainly focus on Interceptors.

Service model


The Service model, in a true sense, models your service. It is a framework of components that represents a service in a WSDL-like model. It provides functionality to create various WSDL elements such as operations, bindings, endpoints, schema, and so on. The following figure shows the various components that form the Service model:

The components of the Service model can be used to create a service. As you can see from the above figure, the service model’s primary component is ServiceInfo which aggregates other related components that make up the complete service model. ServiceInfo is comprised of the following components that more or less represent WSDL elements:

  • InterfaceInfo

  • OperationInfo

  • MessageInfo

  • BindingInfo

  • EndpointInfo


A web service is usually created using one of the frontends offered by CXF. It can be either constructed from a Java class or from a WSDL. CXF frontends internally use the service model to create web services. For example, by using a simple frontend, we can create, publish, and consume web services through factory components such as ServerFactoryBean and ClientProxyFactoryBean. These factory classes internally use the service model of CXF.

Data binding


Data binding is the key for any web service development. Data binding means mapping between Java objects and XML elements. As we know, with web service, messages are exchanged as XML artifacts. So there has to be some way to convert these XML into Java objects and vice versa for the application to process as service and client. Data binding components perform this mapping for you. CXF supports two types of data binding components—JAXB and Aegis. CXF uses JAXB as the default data binding component. As a developer, you have the choice of specifying the binding discipline through a configuration file or API. If no binding is specified, then JAXB is taken as a default binding discipline. The latest version of CXF uses JAXB 2.1. JAXB uses annotations to define the mapping between Java objects and XML. The following code illustrates the use of JAXB annotations:
[code lang=”java”]
@XmlRootElement(name="processOrder", namespace=" http://localhost/
orderprocess")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name="processOrder", namespace=
" http://localhost/orderprocess")
public class OrderProcess {
@XmlElement(name="arg0", namespace="")
private order.Order arg0;
//Gettter and Setter
….
}
[/code]
As shown in the previous code, the @Xml specific annotations represents the JAXB metadata that is used by JAXB to map Java classes to XML schema constructs. For example, the @XmlType annotation specifies that the OrderProcess class will be mapped to complex XSD element type ‘processOrder’ that contains an element ‘arg0’ of type ‘Order’ bean. CXF also supports the Aegis data binding component to map between Java objects and XML. Aegis allows developers to gain control of data binding through its flexible mapping system. You do not have to rely on annotations to devise the mapping. Your Java code is clean and simple POJO. Aegis also supports some annotations that can be used to devise binding. Some of the annotations that can be used with Aegis are:

  • XmlAttribute

  • XmlElement

  • XmlParamType

  • XmlReturnType

  • XmlType


In Aegis, you define the data mapping in a file called <MyJavaObject>.aegis.xml, where MyJavaObject is the object that you are trying to map with XML. Aegis reads this XML to perform the necessary binding. Aegis also uses refl ection to derive the mapping between Java object and XML. The following code fragment shows the sample Aegis mapping file:
[code lang=”xml”]
<?xml version="1.0" encoding="UTF-8"?>
<mappings>
<mapping name="HelloWorld">
<method name="sayHi">
<parameter index="0" mappedName=
"greeting" nillable=’false’ />
</method>
</mapping>
</mappings>
[/code]
The above XML fragment states that a string parameter of a method named sayHiof the bean HelloWorld should be mapped to a name as greeting. You can configure your web service to use Aegis data binding as follows:
[code lang=”xml”]
<jaxws:endpoint id="orderProcess" implementor="demo.order.
OrderProcessImpl" address="/OrderProcess" >
<jaxws:dataBinding>
<bean class="org.apache.cxf.aegis.databinding.AegisDatabinding" />
</jaxws:dataBinding>
</jaxws:endpoint>
[/code]

Protocol binding


Bindings bind the web service’s messages with the protocol-specific format. The messages, in web service terminology, are nothing but an operation with input and output parameters. The message defined in the web service component is called a logical message. The logical message used by a service component is mapped or bound to a physical data format used by endpoints in the physical world. It lays down rules as to how the logical messages will be mapped to an actual payload sent over the wire or network.
Bindings are directly related to port types in a WSDL artifact. Port types define operations and input and output parameters which are abstract in nature. They define the logical message, whereas binding translates this logical message into actual payload data defined by the underlying protocol. The following WSDL portion shows the sample binding details:
[code lang=”xml”]
<wsdl:binding name="OrderProcessImplServiceSoapBinding"
type="tns:OrderProcess">
<soap:binding style="document" transport=
"http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="processOrder">
<soap:operation soapAction="" style="document" />
<wsdl:input name="processOrder">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="processOrderResponse">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
[/code]
As you can see from the above sample binding fragment, it is defined using the <binding> element. This element has two attributes, namely, name and type. The name attribute identifies the binding, and the type attribute maps it with the port type. The name attribute of the binding element is used to associate with the endpoint. The child elements of the <binding> parent element define the actual mapping of the messages with the protocol format. In the previous case, the communication protocol used is SOAP 1.1. CXF supports the following binding protocols:

  • SOAP 1.1

  • SOAP 1.2

  • CORBA

  • Pure XML


Transports


Transport defines the high-level routing protocol to transmit the messages over the wire. Transport protocols are associated with the endpoints. One endpoint can communicate with another using a specific transport protocol. Transport details are nothing but networking details. Service endpoints are a physical representation of a service interface. Endpoints are composed of binding and networking details. In a WSDL artifact, transport details are specified as part of the <port> element. The port element is a child of the service element. The WSDL portion following shows the sample transport details:
[code lang=”xml”]
<wsdl:service name="OrderProcessImplService">
<wsdl:port binding="tns:OrderProcessImplServiceSoapBinding"
name="OrderProcessImplPort">
<soap:address location="http://localhost:8080/orderapp/
OrderProcess" />
</wsdl:port>
</wsdl:service>
[/code]
As you see from the above XML fragment, transport details are specified as part of the service element. The service element has one child element as port element. The port element maps to binding as defined by the binding element and provides details of the transport. The previous example shows SOAP as binding protocol and HTTP as a transport protocol. In Chapter 4, the various transport protocols are explained in the context of web services development. CXF supports the following transports for its endpoints:

  • HTTP

  • CORBA

  • JMS

  • Local

Summary

The chapter started by describing the Order Processing Application and we saw how to develop a web service with CXF and Spring-based configuration. CXF’s seamless integration with Spring makes it extremely easy and convenient to build and publish a web service. We also saw how to build, deploy, and execute a web service using ANT and Tomcat. The chapter later described the CXF architecture, which is built upon the core components. These components lay down the foundation for building web services.

Filed Under: WebServices Tagged With: CXF

Tomcat 6.0 Servlet Container Overview

June 20, 2010 by itadmin Leave a Comment

Tomcat 6.0 Developer’s Guide

Current books on Tomcat are primarily focused on the application deployer or administrator. As a result, they invariably focus on the issues related to managing a Tomcat installation, configuring the runtime environment, and on deploying web applications.

also read:

  • WebLogic Interview Questions
  • JBoss Portal Server Development
  • Tomcat Interview Questions

On the other hand, while books on servlet programming are targeted at Java web developers, they often provide a container-agnostic view of the servlet specification. Tomcat is often a bit player in these books and has very few speaking lines.

This book fills the void between these two approaches.
It will take you on a guided tour of a living implementation of an industrial-strength servlet container.
Along the way, you will learn how various elements of the Servlet 2.5 specification as well as how the HTTP RFCs are implemented.

By the end of your journey, you will have acquired specialist grade skills in a range of technologies that contribute to the arena of Java server-side development.

This book intended to provide Tomcat administrators, deployers, and developers an introduction into the internal workings of the Tomcat servlet container.

At the same time, it provides Java web programmers with a deep appreciation of the Servlet APiby exploring its reference implementation—the Tomcat container.

While this book provides you with the conceptual background of all that is necessary to take your skills to the next level, it assumes that the reader has a general understanding of the Java programming language and Java web programming.

What This Book Covers

Chapter 1—Introduction to Tomcat introduces you to the Tomcat container and provides you with the tools necessary to begin to take it apart. The key objective of this chapter is to allow you to make a current source distribution of Tomcat active in a development environment (Eclipse Galileo) so that you can trace the path that a request takes through the container’s code.

Chapter 2—Servlet APiOverview provides the prerequisite information necessary to navigate the remainder of the book. It describes the Java Enterprise Edition Platform, the HTTP protocol, and the Servlet API, and serves as a refresher for those who are already familiar with Java EE web development.

Chapter 3—Servlet Container Overview introduces the reader to the Tomcat container.
This is the 10,000 foot overview of the container that provides a backdrop to the chapters that follow. All the components of Tomcat are described with just enough detail, so as not to overwhelm the reader with too much information, too early in the process.

Chapter 4—Starting up Tomcat takes a closer look at the startup process for Tomcat. This
is also where you will be first introduced to the Apache Digester project—a key component that we will revisit in later chapters. The chapter ends with an example that demonstrates how a web application can be deployed to a dissected Tomcat container living within an Integrated Development Environment.

Chapter 5—The Server and Service Components discusses the Server component and investigates one of its key services—an implementation of the Java Naming and Directory Interface (JNDI) API. We are also introduced to the Lifecycle interface that almost every component within Tomcat implements in order to participate in a standardized event based listener mechanism. To show JNDiin action, our example considers connecting to a MySQL database to retrieve data.

Chapter 6—The Connector Component introduces our first Tomcat luminary, the Coyote Connector. We take a closer look at the standard Java I/O implementation of an HTTP connector. In this chapter, we get a closer look at socket programming, advanced elements of the HTTP protocol, and the internals of the request processing mechanism.

Chapter 7—The Engine Component describes the first request processing ‘Container’ within Tomcat and gives us an inkling of things to come. We are also introduced to the Pipeline and its Valves, which are the standard request processing mechanism for Tomcat components.

Chapter 8—The Host Component discusses the Tomcat implementation of a Virtual Host. This is the key component responsible for the deployment of web application contexts, as well as for the error page mechanism.

Chapter 9—The Context Component is at the central core of this book. You get an upclose-
and-personal look at how a Context is configured, how it accesses its resources, and how it implements its class loading magic.

Chapter 10—The Wrapper Component takes us to the workhorse of the Tomcat component hierarchy. This component wraps an actual servlet, and as a result is close to a web developer’s heart. In addition to reviewing the mapping rules dictated by the Servlet API, we also look at the implementation of servlet filters and the request dispatcher mechanism.

Chapter 11—The Session Component discusses how sessions are implemented in Tomcat to enable stateful behavior over the stateless HTTP protocol. In addition to looking at some core concepts, such as Java serialization and entropy gathering for random number generation, we look at the standard memory based session implementation, as well as an implementation that uses files to persist sessions.

Servlet Container Overview

In the last chapter, we noted that the Java Enterprise Edition can be considered to be nothing more than a set of specifications, or interfaces, for which service providers are required to provide implementations.

While it is the actual implementation that does all the work, these specifications ensure that each implementation can assume that all its other collaborating pieces work as described by their interfaces. In theory, this allows complex software platforms (such as application servers) to be assembled from constituent implementations, each of which is sourced from a different vendor.

In practice, it is highly unlikely that you will interface an EJB container from WebSphere and a JMS implementation from WebLogic, with the Tomcat servlet container from the Apache foundation, but it is at least theoretically possible.

Note that the term ‘interface’, as it is used here, also encompasses abstract classes. The specification’s APimight provide a template implementation whose operations are defined in terms of some basic set of primitives that are kept abstract for the service provider to implement. For instance, in Chapter 2, we noted that the servlet hierarchy is made up of the Servlet interface, and the GenericServlet and HttpServlet abstract classes within the javax.servlet package.

A service provider is required to make available concrete implementations of these interfaces and abstract classes. For example, the HttpSession interface is implemented by Tomcat in the form of org.apache.catalina.session.StandardSession.

Let’s return to the image of the Tomcat container that we saw in Chapter 1.

As was stated in Chapter 1, the objective of this book is to cover the primary request processing components that are present in this image. Advanced topics, such as clustering and security, are shown as shaded in this image and are not covered.

In this image, the ‘+’ symbol after the Service, Host, Context, and Wrapper instances indicate that there can be one or more of these elements. For instance, a Service may have a single Engine, but an Engine can contain one or more Hosts.
In addition, the whirling circle represents a pool of request processor threads.

In this chapter, we will fl y over the architecture of Tomcat from a 10,000-foot perspective taking in the sights as we go.

Component taxonomy

Tomcat’s architecture follows the construction of a Matrushka doll from Russia. In other words, it is all about containment where one entity contains another, and that entity in turn contains yet another.

In Tomcat, a ‘container’ is a generic term that refers to any component that can contain another, such as a Server, Service, Engine, Host, or Context.

Of these, the Server and Service components are special containers, designated as Top Level Elements as they represent aspects of the running Tomcat instance. All the other Tomcat components are subordinate to these top level elements.

The Engine, Host, and Context components are officially termed Containers, and refer to components that process incoming requests and generate an appropriate outgoing response.

Nested Components can be thought of as sub-elements that can be nested inside either Top Level Elements or other Containers to configure how they function. Examples of n ested components include the Valve, which represents a reusable unit of work; the Pipeline, which represents a chain of Valves strung together; and a Realm which helps set up container-managed security for a particular container.

Other nested components include the Loader which is used to enforce the specification’s guidelines for servlet class loading; th e Manager that supports session management for each web application; the R esources component that represents the web application’s static resources and a mechanism to access these resources; and the Listener th at allows you to insert custom processing at important points in a container’s life cycle, such as when a component is being started or stopped.
[code]
Not all nested components can be nested within every container.
[/code]

A final major component, which falls into its own category, is the Connector. It represents the connection end point that an external client (such as a web browser) can use to connect to the Tomcat container.

Before we go on to examine these components, let’s take a quick look at how they are organized structurally.

Note that this diagram only shows the key properties of each container.

When Tomcat is started, the Java Virtual Machine (JVM) instance in which it runs will contain a singleton Server top level element, which represents the entire Tomcat server. A Server will usually containjust one Service object, which is a structural element that combines one or more Connectors (for example, an HTTP and an HTTPS connector) that funnel incoming requests through to a single Catalina servlet Engine.

The Engine represents the core request processing code within Tomcat and supports the definition of multiple Virtual Hosts within it. A virtual host allows a single running Tomcat engine to make it seem to the outside world that there are multiple separate domains (for example, www.my-site.com and www.your-site.com) being hosted on a single machine.

Each virtual host can, in turn, support multiple web applications known as Contexts that are deployed to it. A context is represented using the web application format specified by the servlet specification, either as a single compressed WAR (Web Application Archive) file or as an uncompressed directory. In addition, a context is configured using a web.xml file, as defined by the servlet specification.

A context can, in turn, contain multiple servlets that are deployed into it, each of which is wrapped in a Wrapper component.

The Server, Service, Connector, Engine, Host, and Context elements that will be present in a particular running Tomcat instance are configured using the server.xml configuration file.
[code]
Things are a bit more complicated than this. However, we’ll defer the
complexity until later chapters when we deal with each component in a
lot more detail.
[/code]

Architectural benefits

This architecture has a couple of useful features. It not only makes it easy to manage component life cycles (each component manages the life cycle notifications for its children), but also to dynamically assemble a running Tomcat server instance that is based on the information that has been read from configuration files at startup.In particular, the server.xml file is parsed at startup, and its contents are used to instantiate and configure the defined elements, which are then assembled into a running Tomcat instance.
[code]
The server.xml file is read only once, and edits to it will not be picked
up until Tomcat is restarted.
[/code]

This architecture also eases the configuration burden by allowing child containers to inherit the configuration of their parent containers. For instance, a Realm defines a data store that can be used for authentication and authorization of users who are attempting to access protected resources within a web application. For ease of configuration, a realm that is defined for an engine applies to all its children hosts and contexts. At the same time, a particular child, such as a given context, may override its inherited realm by specifying its own realm to be used in place of its
parent’s realm.

Top Level Components

The Server and Service container components exist largely as structural conveniences. A Server represents the running instance of Tomcat and contains one or more Service children, each of which represents a collection of request processing components.

Server


A Server represents the entire Tomcat instance and is a singleton within a Java Virtual Machine, and is responsible for managing the life cycle of its contained services.

The following image depicts the key aspects of the Server component. As shown, a Server instance is configured using the server.xml configuration file. The root element of this file is and represents the Tomcat instance. Its default implementation is provided using org.apache.catalina.core.StandardServer, but you can specify your own custom implementation through the className attribute of the element.

A key aspect of the Server is that it opens a server socket on port 8005 (the default) to listen a shutdown command (by default, this command is the text string SHUTDOWN). When this shutdown command is received, the server gracefully shuts itself down. For security reasons, the connection requesting the shutdown must be initiated from the same machine that is running this instance of Tomcat.

A Server also provides an implementation of the Java Naming and Directory Interface (JNDI) service, allowing you to register arbitrary objects (such as data sources) or environment variables, by name.

At runtime, individual components (such as servlets) can retrieve this information by looking up the desired object name in the server’s JNDibindings.

While a JNDiimplementation is not integral to the functioning of a servlet container, it is part of the Java EE specification and is a service that servlets have a right to expect from their application servers or servlet containers. Implementing this service makes for easy portability of web applications across containers.

While there is always just one server instance within a JVM, it is entirely possible to have multiple server instances running on a single physical machine, each encased in its ownjVM. Doing so insulates web applications that are running on one VM from errors in applications that are running on others, and simplifies maintenance by allowing a JVM to be restarted independently of the others. This is one of the mechanisms used in a shared hosting environment (the other is virtual hosting,
which we will see shortly) where you need isolation from other web applications that are running on the same physical server.

Service


While the Server represents the Tomcat instance itself, a Service represents the set of request processing components within Tomcat.

A Server can contain more than one Service, where each service associates a group of Connector components with a single Engine.

Requests from clients are received on a connector, which in turn funnels them through into the engine, which is the key request processing component within Tomcat. The image shows connectors for HTTP, HTTPS, and the Apache JServ Protocol (AJP).

There is very little reason to modify this element, and the default Service instance is usually sufficient.

A hint as to when you might need more than one Service instance can be found in the above image. As shown, a service aggregates connectors, each of which monitors a given IP address and port, and responds in a given protocol. An example use case for having multiple services, therefore, is when you want to partition your services (and their contained engines, hosts, and web applications) by IP address and/or port number.

For instance, you might configure your firewall to expose the connectors for one service to an external audience, while restricting your other service to hosting intranet applications that are visible only to internal users. This would ensure that an external user could never access your Intranet application, as that access would be blocked by the firewall.

The Service, therefore, is nothing more than a grouping construct. It does not
currently add any other value to the proceedings.
[code]
The server and service components are covered in more detail in
Chapter 5, The Server and Service Components.
[/code]

Connectors

A Connector is a service endpoint on which a client connects to the Tomcat container. It serves to insulate the engine from the various communication protocols that are used by clients, such as HTTP, HTTPS, or the Apache JServ Protocol (AJP).

Tomcat can be configured to work in two modes—Standalone or in Conjunction with a separate web server.

In standalone mode, Tomcat is configured with HTTP and HTTPS connectors, which make it act like a full-fl edged web server by serving up static content when requested, as well as by delegating to the Catalina engine for dynamic content.

Out of the box, Tomcat provides three possible implementations of the HTTP/1.1 and HTTPS connectors for this mode of operation.

The most common are the standard connectors, known as Coyo te which are implemented using standard Java I/O mechanisms.

You may also make use of a couple of newer implementations, one which uses the non-blocking NIO features of Java 1.4, and the other which takes advantage of native code that is optimized for a particular operating system through the Apache Portable Runtime (APR).

Note that both the Connector and the Engine run in the same JVM. In fact, they run within the same Server instance.

In conjunction mode, Tomcat plays a supporting role to a web server, such as Apache httpd or Microsoft’s IIS. The client here is the web server, communicating with Tomcat either through an Apache module or an ISAPiDLL. When this module determines that a request must be routed to Tomcat for processing, it will communicate this request to Tomcat using AJP, a binary protocol that is designed to be more efficient than the text based HTTP when communicating between a web server and Tomcat.

On the Tomcat side, an AJP connector accepts this communication and translates it into a form that the Catalina engine can process.

In this mode, Tomcat is running in its ownjVM as a separate process from the web server.

In either mode, the primary attributes of a Connector are the IP address and port on which it will listen for incoming requests, and the protocol that it supports. Another key attribute is the maximum number of request processing threads that can be created to concurrently handle incoming requests. Once all these threads are busy, any incoming request will be ignored until a thread becomes available.

By default, a connector listens on all the IP addresses for the given physical machine (its address attribute defaults to 0.0.0.0). However, a connector can be configured to listen onjust one of the IP addresses for a machine. This will constrain it to accept connections from only that specified IP address.

Any request that is received by any one of a service’s connectors is passed on to the service’s single engine. This engine, known as Catalina, is responsible for the processing of the request, and the generation of the response.

The engine returns the response to the connector, which then transmits it back to the client using the appropriate communication protocol.
[code]
This component is covered in more detail in Chapter 6,
The Connector Component.
[/code]

Container components

In this section, we’ll take a look at the key request processing components within Tomcat; the engine, virtual host, and context components.

Engine


An Engine represents a running instance of the Catalina servlet engine and comprises the heart of a servlet container’s function. There can only be one engine within a given service. Being a true container, an Engine may contain one or more virtual hosts as children.

Being the primary request processing component, it receives objects that represent the incoming request and the outgoing response. Its main function is to delegate the processing of the incoming request to the appropriate virtual host. If the engine has no virtual host with a name matching the one to which the request should be directed, it consults its defaultHost attribute to determine the host that should be used.

Virtual host


A virtual host in Tomcat is represented by the Host component, which is a container for web applications, or, in Tomcat parlance, contexts.

Two key concepts come into play when working with virtual hosts—the host’s domain name and its application base folder.


  • Domain name: Each virtual host is identified by the domain name that you registered for use with this host. This is the value that you expect the client browser to send in the Host: request header. A host’s name is required to be unique within its containing engine.

  • Application base folder: This fo lder is the location that contains the contexts that will be deployed to this host. This folder location can either be specified as an absolute path or as a path relative to CATALINA_BASE.


[code]
CATALINA_HOME is an environment variable that references the location
of the Tomcat binaries. The CATALINA_BASE environment variable
makes it possible to use a single binary installation of Tomcat to run
multiple Tomcat instances with different configurations (which are
primarily determined by the contents of the conf folder).
In addition, the use of a CATALINA_BASE location that is separate
from CATALINA_HOME keeps the standard binary distribution separate
from your installation. This has the beneficial effect of making it easy
to upgrade to a newer Tomcat version, without having to worry about
clobbering your existing web applications and related configuration files.
This component is covered in more detail in Chapter 7,
The Engine Component.
[/code]

Basic concepts


When it comes to mapping host names to Internet Protocol addresses, the simplest scenario is one in which a given Fully Qualified Host Name (FQHN), such as www.swengsol.com, is associated with the IP address that maps to a particular physical host.

The downside with this approach is that connecting a host to the Internet is fairly expensive. This is especially true when you consider the costs related to bandwidth, infrastructure (such as database/mail servers, firewalls, uninterruptible power supplies, fault tolerance, and so on), and maintenance (including staffing, administration, and backups), not to mention having to obtain an IP address in the first place.

As a result, many small businesses find it preferable to lease space and infrastructure from hosting service providers. The hosting service may have a single physical server that is connected to the Internet and is identified with a specific IP address. This physical server could host several domains on behalf of the provider’s customers.

For example, consider the case where Acme Widgets Inc. and Vertico LLC have their domains, www.acme-widgets.com and www.vertico.com, hosted on a single physical machine at a hosting service. The applications that are deployed to both these domains must be able to function without any interference from the other.

In this case, both these domains are termed ‘virtual’ hosts, in the sense that they appear to be represented by separate physical hosts. However, in reality, they exist simply as a logical partitioning of the address space on a single physical host.

Virtual host techniques


There are two common ways to set up virtual hosting:

  • IP-based virtual hosting

  • Name-based virtual hosting

IP-based virtual hosting


With this technique, each FQHN resolves to a separate IP address. However, each of these IP addresses resolves to the same physical machine.

You can achieve this by using either of the following mechanisms:

  • A multi-homed server, that is, a machine that has multiple physical Network Interface Cards (NICs) installed, each of which has an assigned IP address.

  • Using operating system facilities to set up virtual network interfaces by dynamically assigning multiple IP addresses to a single physical NIC.


In either case, the downside is that we need to acquire multiple IP addresses, and these addresses (at least for IPv4) are a limited resource.

The web server is configured to listen on ports that are assigned to each of these IPaddresses, and when it detects an incoming request on a particular IP address, it generates the response appropriate for that address.

For example, you can have a web server that is running on a particular physical host that is monitoring port 80 on both 11.156.33.345 and 11.156.33.346. It is configured to respond to requests that are coming in on the former IP address with content that is associated with a particular host name, say www.host1.com, whereas it is www.host2.com for the latter.

When a request comes in on 11.156.33.346, the server knows that it should serve content from the www.host2.com, and does so. To the user, this is indistinguishable from an entirely separate physical server.

Name-based virtual hosting



This is a newer technique that lets you map different domain names to the same IP address. The domain names are registered as normal, and multiple DNS entries exist to map these domain names to the same IP address.

The HTTP/1.1 protocol requires that every request must contain a Host: header that carries the fully qualified host name, as well as the port number (if specified) to which the user wishes to connect. The web server that runs on the host at the IP address will receive this request and will read this header to determine the specific virtual host that should handle this request.

Name-based virtual hosting is preferred for its simplicity and for the fact that it does not use up IP addresses needlessly.

However, you may have to use IP-based virtual hosting when you are using virtual hosts together with SSL. The reason is that the negotiation protocol commits to a certificate before it pays heed to the specific virtual host for which the request is being made. This is because the SSL protocol layer works at a lower level than the HTTP protocol, and the module negotiating this handshake with the client cannot read the HTTP request header until the handshake is complete.
[code]
You may be able to use name-based virtual hosting with SSL if
your web server and client supports the Server Name Indication
extension as specified in RFC 3546—Transport Layer Security
Extensions (http://www.ietf.org/rfc/rfc3546.txt).
Using this extension, during the SSL negotiation, the client also
transmits the host name to which it is trying to connect, thereby
allowing the web server to handle the handshake appropriately
by returning the certificate for the correct host name.
[/code]

Virtual host aliasing


Aliasing works by informing the web server that if it sees the aliased domain name in the Host: header, it should be treated in exactly the same manner as the virtual host’s domain name.

For example, if you set up swengsol.com as an alias for the www.swengsol.com virtual host, then typing either domain name in the URL will result in the same virtual host being used to process the request.

This works well when a particular host may be known by more than one domain name, and you don’t want to clutter your configuration file by creating one set of entries per alias that a user may use to connect to that host.
[code]
This component is covered in more detail in Chapter 8,
The Host Component.
[/code]

Context


A Context, or web application, is where your application specific code (servlets and JSPs) live. It provides a neat way to organize the resources that comprise a given web application.

A context maps to a ServletContext instance within the servlet specification. In many ways, the servlet specification is primarily concerned with this context component. For instance, it mandates the format for deploying a context, and dictates the contents of the deployment descriptor.

Important attributes for a context include:


  • Document base: This is the path name, either absolute or relative to its containing host’s application base, to where its WAR file or exploded folder (its content root) are located.

  • Context path: It represents the portion of the URL that uniquely identifies a web application within a given host. It helps the host container to determine which of its deployed contexts should be responsible for handling an incoming request.

    One of your contexts may be identified as the default context. This context is then the application that will be invoked when no context path is specified on the URL. This default context is identified by specifying an empty string as its context path, and as such, can be referenced by using a URL that only specifies a hostname. The default application is identified in Tomcat by a
    folder named ROOT in the application base folder for a given host.


  • Automatic reload: A c ontext’s resources can be monitored for changes, and the context reloaded automatically when any changes are detected. While this is remarkably useful during development, this is an expensive operation and should be turned off in production.


Context configuration


A Context is unique because it has multiple options when it comes to its configuration. We have already noted the presence of the conf/server.xml file that is used to set up the overall structure of the Tomcat instance. While this file’s element can be used to configure a context, this is no longer recommended.

Instead, Tomcat lets you configure a Context by letting you extract the element from the server.xml file and move it into a separate file called a context fragment file. Context fragments are monitored and reloaded by Tomcat at runtime.
[code]
Note that the server.xml file is only ever loaded once at startup.
[/code]

To ensure a clear separation of contexts by host and engine, Tomcat expects to find context fragments using a specific directory path CATALINA_HOME/conf/ //. The context fragments for contexts deployed into this host are found within this folder and are named .xml.

For the default case, that is, an engine named Catalina and a host named localhost, this works out to be the folder CATALINA_HOME/conf/Catalina/ localhost. However, the name of the host could be any valid domain name, for example, www.swengsol.com, resulting in a folder named CATALINA_HOME/conf/
Catalina/www.swengsol.com.

In addition, context fragments may also be found embedded within the META-INF folder of a web application’s WAR file or exploded directory. In such cases, the fragment must be named context.xml.

Contexts can also be configured using the web application deployment descriptor, web.xml. While the fragment file is proprietary to Tomcat, the deployment descriptor is described by the servlet specification, and therefore is portable across Java EE compliant servlet containers. We will consider both of these in much greater detail in later chapters.
[code]
This component is covered in more detail in Chapter 9,
The Context Component.
[/code]

Wrapper

A Wrapper object is a child of the context container and represents an individual servlet (or a JSP file converted to a servlet). It is called a Wrapper because it wraps an instance of a javax.servlet.Servlet.

This is the lowest level of the Container hierarchy, and any attempt to add a child to it will result in an exception being thrown.

A wrapper is responsible for the servlet that it represents, including loading it, instantiating it, and invoking its lifecycle methods such as init(), service(), and destroy().

It is also responsible, through its basic valve, for the invocation of the filters that are
associated with the wrapped servlet.
[code lang=”java”]
This component is covered in more detail in Chapter 10,
The Wrapper Component.
[/code]

Nested components

These components are specific to the Tomcat implementation, and their primary purpose is to enable the various Tomcat containers to perform their tasks.

Valve

A valve is a processing element that can be placed within the processing path of each of Tomcat’s containers—engine, host, context, or a servlet wrapper. A Valve is added to a container using the element in server.xml. They are executed in the order in which they are encountered within the server.xml file.

The Tomcat distribution comes with a number of pre-rolled valves. These include:


  • A valve that logs specific elements of a request (such as the remote client’s IPaddress) to a log file or database

  • A valve that lets you control access to a particular web application based on the remote client’s IP address or host name

  • A valve that lets you log every request and response header

  • A valve that lets you configure single sign-on access across multiple web applications on a specific virtual host

If these don’t meet your needs, you can write your own implementations of
org.apache.catalina.Valve and place them into service.

A container does not hold references to individual valves. Instead, it holds a reference to a single entity known as the Pipeline, which represents a chain of valves associated with that container.

When a container is invoked to process a request, it delegates the processing to its associated pipeline.

The valves in a pipeline are arranged as a sequence, based on how they are defined within the server.xml file. The final valve in this sequence is known as the pipeline’s basic valve. This valve performs the task that embodies the core purpose of a given container.

Unlike individual valves, the pipeline is not an explicit element in server.xml, but instead is implicitly defined in terms of the sequence of valves that are associated with a given container.

Each Valve is aware of the next valve in the pipeline. After it performs its pre processing, it invokes the next Valve in the chain, and when the call returns, it performs its own post processing before returning.

This is very similar to what happens in filter chains within the servlet specification.

In this image, the engine’s configured valve(s) fire when an incoming request is received. An engine’s basic valve determines the destination host and delegates processing to that host. The destination host’s (www.host1.com) valves now fire in sequence. The host’s basic valve then determines the destination context (here, Context1) and delegates processing to it. The valves configured for Context1 now fire and processing is then delegated by the context’s basic valve to the appropriate wrapper, whose basic valve hands off processing to its wrapped servlet.
The response then returns over the same path in reverse.
[code]
A Valve becomes part of the Tomcat server’s implementation and
provides a way for developers to inject custom code into the servlet
container’s processing of a request. As a result, the class files for custom
valves must be deployed to CATALINA_HOME/lib, rather than to the
WEB-INF/classes of a deployed application.
[/code]
As they are not part of the servlet specification, valves are non-portable elements of your enterprise application. Therefore, if you rely on a particular valve, you will need to find equivalent alternatives in a different application server.

It is important to note that valves are required to be very efficient in order not to introduce inordinate delays into the processing of a request.
[code]
The valve and pipeline components are covered in more detail in
Chapter7, The Engine Component.
[/code]

Realm

Container managed security works by having the container handle the authentication and authorization aspects of an application.
Authentication is defined as the task of ensuring that the user is who she says she is, and authorization is the task of determining whether the user may perform some specific action within an application.

The advantage of container managed security is that security can be configured declaratively by the application’s deployer. That is, the assignment of passwords to users and the mapping of users to roles can all be done through configuration, which can then be applied across multiple web applications without any coding changes being required to those web applications.
[code]
Application Managed Security
The alternative is having the application manage security. In this case,
your web application code is the sole arbiter of whether a user may access
some specific functionality or resource within your application.
[/code]

For Container managed security to work, you need to assemble the following components:


  • Security constraints: Within your web application’s deployment descriptor, web.xml, you must identify the URL patterns for restricted resources, as well as the user roles that would be permitted to access these resources.

  • Credential input mechanism: In th e web.xml deployment descriptor, you specify how the container should prompt the user for authentication credentials. This is usually accomplished by showing the user a dialog that prompts the user for a user name and password, but can also be configured to use other mechanisms such as a custom login form.

  • Realm: This is a dat a store that holds user names, passwords, and roles, against which the user-supplied credentials are checked. It can be a simple XML file, a table in a relational database that is accessed using the JDBC API, or a Lightweight Directory Access Protocol (LDAP) server that can be accessed through the JNDiAPI. A realm provides Tomcat with a consistent
    mechanism of accessing these disparate data sources.

All three of the above components are technically independent of each other. The power of container based security is that you can assemble your own security solution by mixing and matching selections from each of these groups.

Now, when a user requests a resource, Tomcat will check to see whether a security constraint exists for this resource. For a restricted resource, Tomcat will then automatically request the user for her credentials and will then check these credentials against the configured realm. Access to the resource will be allowed only if the user’s credentials are valid and if the user is a member of the role that is configured to access that resource.

Executor

This is a new element, available only since 6.0.11. It allows you to configure a shared thread pool that is available to all your connectors. This places an upper limit on the number of concurrent threads that may be started by your connectors.
Note that this limit applies even if a particular connector has not used up all the
threads configured for it.

Listener

Every major Tomcat component implements the org.apache.catalina.Lifecycle interface. This interface lets interested listeners to register with a component, to be notified of lifecycle events, such as the starting or stopping of that component.

A listener implements the org.apache.catalina.LifecycleListener interface and implements its lifecycleEvent() method, which takes a LifecycleEvent that represents the event that has occurred.

This gives you an opportunity to inject your own custom processing into Tomcat’s lifecycle.

Manager

Sessions allows ‘applications’ to be made possible over the stateless HTTP protocol. A session represents a conversation between a client and a server and is implemented by a javax.servlet.http.HttpSession instance that is stored on the server and is associated with a unique identifier that is passed back by the client on each interaction.

A new session is created on request and remains alive on the server either until it times out after a period of inactivity by its associated client, or until it is explicitly invalidated, for instance, by the client choosing to log out.

The above image shows a very simplistic view of the session mechanism within Tomcat.

An org.apache.catalina.Manager component is used by the Catalina engine to create, find, or invalidate sessions. This component is responsible for the sessions that are created for a context and their life cycles.

The default Manager implementation simply retains sessions in memory, but supports session survival across server restarts. It writes out all active sessions to disk when the server is stopped and will reload them into memory when the server is started up again.

A must be a child of a element and is responsible for managing the sessions associated with that web application context.

The default Manager takes attributes such as the algorithm that is used to generate its session identifiers, the frequency in seconds with which the manager should check for expired sessions, the maximum number of active sessions supported, and the file in which the sessions should be stored.

Other implementations of Manager are provided that let you persist sessions to a durable data store such as a file or a JDBC database.
[code]
This component is covered in more detail in Chapter 11,
The Manager Component.

[/code]

Class Loader

This element represents the class loader for a given web application. A class loader is
a very sacred entity injava. In its most basic form, it is responsible for locating the bytecode that represents a compiled Java class and interpreting it.

The bytecode for a given class may be found in a variety of locations, the most common being either on the local file system or over the network. A class loader’s primary goal is to abstract away the process of how the bytes are obtained and reconstituted into a class in memory.

Delegation model


Since Java 2, the class loading mechanism has used a delegating model, where the class loaders within a JVM are organized in a parent-child hierarchy. It is recommended that each class loader first delegate the task of finding and loading a class to its parent before it may attempt to do so itself.

This delegation mechanism ensures that no application can load in a malicious version of a system class (such as java.lang.Object) that may then compromise the integrity of the applications that are running in the JVM.

At the top of this class loader hierarchy is the Bootstrap class loader, called the primordial class loader, which is written in native code and is part of the JVM itself. Being part of the JVM ensures that there is at least one class loader that can be relied upon to load the core Java classes, such as java.lang.Object. This class loader is responsible for loading classes from the core Java packages (such as java.lang or java.util). In the SunjVM implementation, these classes are found injAVA_HOME/jre/lib/rt.jar. The Bootstrap class loader is unique in that, it is at the top of the tree, and so has no parent class loader.

Next down the hierarchy is the Extension class loader which, in the SunjVM, is a java.net.URLClassLoader that monitors the JAVA_HOME/jre/lib/ext folder for extensionjARs. Any JARs placed in this folder are automatically loaded without needing to be on the class path.

Finally, there is the System class loader (or Application class loader), which is also a
URLClassLoader in the SunjVM implementation. It monitors the folders and JARs that are described in the CLASSPATH. This class loader is responsible for loading the
application’s main class.

If a normal application needs to load a class (such as java.lang.String), it will first ask the System class loader for it. The System class loader delegates to the Extension class loader, which in turn delegates to the Bootstrap class loader, which locates the String.class file in rt.jar, loads the class and makes it available as an instance of java.lang.Class.

If an application-specific class file, such as com.swengsol.UserModel.class, is requested, the delegation process works just as before. However, this time the Bootstrap class loader is unable to locate this class in rt.jar. Next, it is the turn of the Extension class loader, and it too is unsuccessful. Finally, the System class loader has a go, and locates the class on its CLASSPATH. This class is then loaded and made
available for the JVM to use.

Caching occurs within each class loader, so each must first check its own cache to see if the class was loaded earlier. If a hit is found, then the class is returned right away.
In our previous example, if the application needed to use another String, then the
Bootstrap class loader would return its cached instance of the String class.
[code]
Endorsed Standards Override Mechanism
Both J2SE 1.4 and 1.5 include a Java APifor XML Processing Parser. The
classes for this parser are loaded by the Bootstrap class loader, and so
take precedence over any parser that you might have installed on your
classpath, even if you have a newer version of the parser classes installed.
The Endorsed Standards Override Mechanism lets you place overrides
to certain classes (CORBA and JAXP classes) in the JAVA_HOME/lib/
endorsed folder. The Bootstrap loader will then load these preferentially
over any classes that it might otherwise find. For details on this
mechanism, see http://java.sun.com/j2se/1.5.0/docs/guide/
standards/.
[/code]
Some interesting points to note about class loading are as follows:


  • A class is considered fully qualified only when it is described in terms of its package name, its class name, and the class loader instance that was used to load that class. In other words, the same class loaded by two different class loaders is treated as two distinct classes. This has implications for the assignment of instances of this class and treatment of static fields or
    singletons, even within a single JVM.

  • Each class loader can only see the class locations that are above it in the hierarchy. For example, a JAR in the Extension folder cannot use a class file on the application’s CLASSPATH. This is because the classes in the Extension folder can only see classes that are served up by either the Extension class loader or the Bootstrap class loader.

  • When code in a class references another class, the referenced class is loaded using the same class loader that loaded the referencing class, called its defining class loader. The defining class loader for a class can be obtained using Class.getClassLoader().

  • Every thread has a context class loader that can be accessed using Thread. currentThread().getContextClassLoader(). Every time a thread is created, its context class loader is set to that of its creating thread. The class loader for the main() thread is the System class loader, which is automatically propagated down to each worker thread, unless you intervene
    by invoking Thread.currentThread().setContextClassLoader().


Java EE class loading


The Java EE world throws in a bit of a twist into this model.

A servlet container is required to provide a restricted environment for its web applications.

If a servlet were to directly use the System class loader, then it would be able to see every class that was on the class path for the JVM command that was used to start Tomcat. This is potentially a security risk, as a malicious web application (as in a hosting vendor’s deployment) may be able to load classes of its sibling web applications.

As a result, each web application must be given its very own class loader, which is placed at the bottom of the tree and preferentially loads classes that are found in the WEB-INF/classes and WEB-INF/lib folders of the web application directory.

This custom class loader will only delegate to its parent class loader when the class that is being requested is one of the standard Java classes.

When a web application needs any other class, instead of delegating to its parent, this custom class loader will first check within the WEB-INF\classes and WEB-INF\lib folders.
Only if it is not found there will it delegate to its parent class loader, which will then follow the standard delegating pattern.

Tomcat’s additional class loaders Endorsed Standards



During startup, Tomcat first neutralizes the System class loader by clearing out the CLASSPATH and resetting it to point to CATALINA_HOME/bin/bootstrap.jar (for the classes required for Tomcat to start up), tomcat-juli.jar (for logging), and tools.jar (for the JSP compiler). This leaves the System class loader useful only for loading a minimal set of Tomcat-specific classes.

Tomcat also changes the endorsed directory to point to CATALINA_HOME/endorsed.

Below it, Tomcat establishes its own hierarchy of class loaders by appending the Server class loader, the Shared class loader, the Co mmon class loader, and one web application class loader per deployed application.

When a web application needs to load a class, the request first comes to the web application class loader, which is responsible (as described above) for loading the classes in the web application’s WEB-INF/classes and WEB-INF/lib folders.

This class loader first delegates to the System class loader to allow the delegation hierarchy to locate any core Java classes. If the requested class cannot be found, then the web application class loader attempts to locate the class within its own repositories. If the class is still not found, it will delegate to the Common class loader, or to the Shared class loader if it is installed.

The Shared class loader and the Server class loader are not instantiated by default. You can enable them by editing the CATALINA_HOME/conf/catalina.properties file and adding the shared.loader and server.loader entries.

The Common class loader monitors the contents of the CATALINA_HOME/lib folder, which contains commonly used JARs such as servlet-api.jar, jasper.jar, coyote.jar, and jsp-api.jar.

Classes that are placed in the Shared loader directory will be available to all web applications, but not to Tomcat’s internal classes, whereas classes that are placed in the Server loader directory will be available only to Tomcat’s internal classes.

Class reloading in web applications


Having a web application-specific class loader enables Tomcat to support class reloading.

When a context needs to be redeployed or when a class needs to be reloaded (such as when a recompiled class file is copied into WEB-INF\classes), the entire web application class loader is discarded, and a brand new instance is created to load all the classes for this web application.

This new class loader is now used to service all future requests.
[code]
This component is covered in more detail in Chapter 9,
The Context Component.
[/code]

Logger

The Logger element in server.xml has been deprecated since Tomcat 5.5. Instead, logging in Tomcat 6 is based on the Java Logging APithat was introduced injava 1.4.

Java Logging could only be configured at the entire JVM level and not at the per class loader level. To allow a different configuration file per web application, Tomcat implemented its own Java Logging implementation, known as JULI and implemented in CATALINA_HOME/bin/tomcat-juli.jar.

The global CATALINA_HOME/conf/logging.properties file controls the debug log settings. In addition, each web application can have its own logging configuration file, WEB-INF/classes/logging.properties.

As shown in the image above, logging is comprised of the following components:


  • Logger: All logging requests are made to Logger objects. These objects are arranged in a hierarchy, rooted at a root logger. This hierarchy mirrors the package hierarchy of classes. Properties can be tied to any level within this hierarchy, and a child Logger inherits properties from its parent.

  • Handler: It specifies the location where log messages should be sent. Options include a ConsoleHandler (which writes to the console), a FileHandler (which writes to a file), and a SocketHandler (which writes to a TCP socket).

  • Level: This is one of seven levels, SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST, OFF (disabled), and ALL (all messages logged), that define which message types are logged.

  • Formatter: This element determines how the information is formatted for display. Tomcat provides both a SimpleFormatter and an XMLFormatter for this purpose.

Resources

The resources associated with a web application context include static resources such as classes, HTML, JSP, and CSS files. These resources may exist in a variety of storage formats. By default, Tomcat supports retrieval of resources from either a compressed WAR file, or from an exploded folder laid out in the WAR format.

It is conceivable that a context’s resources may also be accessed from alternative storage mechanisms, such as a JDBC database. The Resources component makes this possible.

Tomcat provides a directory service implementation of the JNDiAPI, that supports access of resources in a storage-agnostic manner.
[code]
This mechanism is covered in more detail in Chapter 9,
The Context Component.
[/code]

Summary

That was a lot to take in, but now that you are done, rest assured that you understand the overall architecture of Tomcat. We looked at some of the core building blocks of Tomcat and saw how a running Tomcat instance was composed of the various Top Level Components, Connectors, and Nested Components. In the next few chapters, we will take the request processing components that were identified in this chapter and examine them in a lot more detail. But before we get there, we have one more stop to make. In the next chapter, we will explore the bootstrapping process for Tomcat.

Filed Under: Servers Tagged With: Tomcat, Tomcat 6.0

AJAX and PHP

June 7, 2010 by itadmin Leave a Comment

Building Modern Web Applications – Second Edition

AJAX is a complex phenomenon that means different things to different people. Computer users appreciate that their favorite websites are now friendlier and feel more responsive. Web developers learn new skills that empower them to create sleek web applications with little effort. Indeed, everything sounds good about AJAX! At its roots, AJAX is a mix of technologies that lets you get rid of the evil page reload, which represents the dead time when navigating from one page to another. Eliminating page reloads is just one step away from enabling more complex features into websites, such as real-time data validation, drag-and-drop, and other tasks that weren’t traditionally associated with web applications. Although the AJAX ingredients are mature (the XMLHttpRequest object, which is the heart of AJAX, was created by Microsoft in 1999), their new role in the new wave of web trends is very young, and we’ll witness a number of changes before these technologies will be properly used to the best benefit of the end users.

also read:

  • HTML Tutorials
  • CSS Tutorials
  • JavaScript Tutorials

AJAX isn’t, of course, the answer to all the Web’s problems, as the current hype around it may suggest. As with any other technology, AJAX can be overused, or used the wrong way. AJAX also comes with problems of its own: you need to fight with browser inconsistencies, AJAX-specific pages don’t work on browsers without JavaScript, they can’t be easily bookmarked by users, and search engines don’t always know how to parse them. Also, not everyone likes AJAX. While some are developing enterprise architectures using JavaScript, others prefer not to use it at all. When the hype is over, most will probably agree that the middle way is the wisest way to go for most scenarios.
In AJAX and PHP: Building Modern Web Applications – Second Edition, we take a pragmatic and safe approach by teaching relevant patterns and best practices that we think any web developer will need sooner or later. We teach you how to avoid the common pitfalls, how to write efficient AJAX code, and how to achieve functionality that is easy to integrate into current and future web applications, without requiring you to rebuild the whole solution around AJAX. You’ll be able to use the knowledge you learn from this book right away, in your PHP web applications.

What This Book Covers

Chapter 1: The World of AJAX and PHP is all about a quick introduction to the world of AJAX. In order to proceed with learning how to build AJAX applications, it’s important to understand why and where they are useful. It describes the XMLHttpRequest object, which is the key element that enables the client-side JavaScript code to call a page on the server asynchronously.
Chapter 2: JavaScript and the AJAX Client walks you through many fields such as working with HTML, JavaScript, CSS, the DOM, XML, and XMLHttpRequest. It discusses the theory (and practice) that you will need to know to make these components come together smoothly, and form a solid foundation for your future AJAX applications. It also shows you how to implement simple error-handling techniques, and how to write code efficiently.
Chapter 3: Object Oriented JavaScript covers a large area of what object-oriented programming means in the world of JavaScript starting from basic features and going far into the execution context of functions. It teaches you the basic OOP concepts—encapsulation, polymorphism, and inheritance, how to work with JavaScript objects, functions, classes, and prototypes, how to simulate private, instance, and static class members in JavaScript, what the JavaScript execution context is, how to implement inheritance by using constructor functions and prototyping, and the basics of JSON.
Chapter 4: Using PHP and MySQL on the Server starts putting the server to work, using PHP to generate dynamic output, and MySQL to manipulate and store the backend data. This chapter shows you how to use XML and JSON with PHP (so that you can create server-side code that communicates with your JavaScript client), how to implement errorhandling code in your server-side PHP code, and how to work with MySQL databases.
Chapter 5: AJAX Form Validation creates a form validation application that implements traditional techniques with added AJAX flavor, thereby making the form more userfriendly, responsive, and pleasing. The intention of this chapter isn’t to build the perfect validation technique but, rather, a working proof of concept that takes care of user input and ensures its validity.
Chapter 6: Debugging and Profiling AJAX Applications teaches how to enable and use Internet Explorer’s debugging capabilities. It shows how you can work with Web Development Helper, Developer Toolbar, and other Internet Explorer tools and with Firefox plugins such as Firebug, Venkman JavaScript Debugger, and Web Developer.
Chapter 7: Advanced Patterns and Techniques briefly covers some of the most important patterns and techniques covering usability, security, and techniques. Looking at methods, patterns, and techniques is so important that it has developed into its own science and has
created a set of guidelines for typical problems that offer us predictable results.
Chapter 8: AJAX Chat with jQuery teaches how to use AJAX to easily implement an online chat solution. This will also be your opportunity to use one of the most important JavaScript frameworks around—jQuery. More precisely, this chapter will explain the
basics of jQuery and show how to create a simple, yet efficient clientserver chat mechanism using AJAX.
Chapter 9: AJAX Grid explains the usage of an AJAX-enabled data grid plugin, jqGrid.
Appendix: Preparing Your Working Environment covers the installation instructions that set up your machine for the exercises in this book. It also covers preparing the database that is used in many examples throughout the book.

AJAX Form Validation

Input data validation is an essential feature for any modern software application. In the case of web applications, validation is an even more sensitive area because your application is widely reachable by many users with varying skill sets (and intentions). Validation is not something that you can play with—invalid data has the potential to harm the application’s functionality, result in errant and inaccurate reporting, and even corrupt the application’s most sensitive area—the database.
Validating data requires checking whether the data entered by the user complies with rules established in accordance with the business rules of your application before allowing it to be used. For example, if dates must be entered in the YYYY-MM-DD format, then a date of February 28 would be invalid. Email addresses and phone numbers are other examples of data that should be checked against valid formats.
In addition, validation must guard against “SQL injection”—which could corrupt, control, and/or access your data and database.

The importance of carefully defining input data validation rules
and consistently applying those rules cannot be overstated!

Historically, web form validation was implemented primarily on the server side, after the form was submitted. In some cases, on the client side, there was also some JavaScript code that performed simple validation such as checking whether the email address was valid or if a field had been left blank. But, there were a few problems with traditional web form validation techniques:


  • Server-side form validation butted up against the limits of the HTTP protocol—a stateless protocol. Unless special code was written to deal with this issue, submitting a page with invalid data had the user receiving an empty form as a reply, and then, much to his chagrin, the entire form had to be filled in again from scratch. How annoying.

  • After submitting the page, the user waited (not so) patiently for a full-page reload. With every mistake made in filling out the form, the annoying “new page reload with blank form” happened.


In this chapter, we will create a form validation application that implements traditional techniques with added AJAX fl avor, thereby making the form more user-friendly, responsive, and pleasing. In the AJAX world, entered data is validated on the fly, so the users are never confronted with waiting for full-page reloads or the rude “blank form” as a reply. The server is the last line of defense against invalid data, so even if you implement client-side validation, server-side validation is mandatory. The JavaScript code that
runs on the client can be disabled permanently from the browser’s settings and/or it can be easily modified or bypassed.

Implementing AJAX form validation

The form validation application we will build in this chapter validates the form at the server side on the classic form submit, implementing AJAX validation while the user navigates through the form. The final validation is performed at the server, as shown in Figure 5-1:

Doing a final server-side validation when the form is submitted should never be considered optional. If someone disables JavaScript in the browser settings, AJAX validation on the client side clearly won’t work, exposing sensitive data, and thereby allowing an evil-intentioned visitor to harm important data on the server (forexample, through SQL injection).

Always validate user input on the server.

As shown in the preceding figure, the application you are about to build validates a registration form using both AJAX validation (client side) and typical server-side validation:


  • AJAX-style (client side): It happens when each form field loses focus (onblur). The field’s value is immediately sent to and evaluated by the server, which then returns a result (0 for failure, 1 for success). If validation fails, an error message will appear and notify the user about the failed validation, as shown in Figure 5-3.

  • PHP-style (server side): This is the usual validation you would do on the server—checking user input against certain rules after the entire form is submitted. If no errors are found and the input data is valid, the browser is redirected to a success page, as shown in Figure 5-4. If validation fails, however, the user is sent back to the form page with the invalid fields highlighted, as shown in Figure 5-3.


Both AJAX validation and PHP validation check the entered data against our application’s rules:

  • Username must not already exist in the database

  • Name field cannot be empty

  • A gender must be selected

  • Month of birth must be selected

  • Birthday must be a valid date (between 1-31)

  • Year of birth must be a valid year (between 1900-2000)

  • The date must exist in the number of days for each month (that is, there’s no February 31)

  • E-mail address must be written in a valid email format

  • Phone number must be written in standard US form: xxx-xxx-xxxx

  • The I’ve read the Terms of Use checkbox must be selected


Watch the application in action in the following screenshots:


XMLHttpRequest, version 2

As in this book we do our best to combine theory and practice, before moving on to implementing the AJAX form validation script, we’ll have another quick look at our favorite AJAX object—XMLHttpRequest. On this occasion, we will step up the complexity (and functionality) a bit and use everything we have learned until now. We will continue to build on what has come before as we move on; so again, it’s important that you take the time to be sure you’ve understood what we are doing here. Time spent on digging into the materials
really pays off when you begin to build your own application in the real world. In Chapter 2, we took a sneak peak at the XMLHttpRequest object—the nexus of the AJAX world. Back then, we didn’t have any OOP JavaScript skills. We’ve seen the power hidden in JavaScript in Chapter 3. In Chapter 4, we saw how PHP works together with AJAX requests.
Our OOP JavaScript skills will be put to work improving the existing script that used to make AJAX requests. In addition to the design that we’ve already discussed, we’re creating the following features as well:


  • Flexible design so that the object can be easily extended for future needs and purposes

  • The ability to set all the required properties via a JSON object


We’ll package this improved XMLHttpRequest functionality in a class named XmlHttp that we’ll be able to use in other exercises as well. You can see the class diagram in the following screenshot, along with the diagrams of two helper classes:

  • settings is the class we use to create the call settings; we supply an instance of this class as a parameter to the constructor of XmlHttp

  • complete is a callback delegate, pointing to the function we want executed when the call completes


The final purpose of this exercise is to create a class named XmlHttp that we can easily use in other projects to perform AJAX calls. This class is an improvement of the async.js script that you built in Chapter 2, JavaScript and the AJAX Client.

With our goals in mind, let’s get to it!

Time for action – the XmlHttp object



  1. In the ajax folder, create a folder named validate, which will host the exercises in this chapter.

  2. In the validate folder, create a new file named xhr.js and add the following code to it:

  3. [code lang=”java”]
    // XmlHttp constructor can receive request settings:
    // url – the server url
    // contentType – request content type
    // type – request type (default is GET)
    // data – optional request parameters
    // async – whether the request is asynchronous (default is true)
    // showErrors – display errors
    // complete – the callback function to call when the request
    // completes
    function XmlHttp(settings)
    {
    // store the settings object in a class property
    this.settings = settings;
    // override default settings with those received as parameter
    // the default url points to the current page
    var url = location.href;
    if (settings.url)
    url = settings.url;
    // the default content type is the content type for forms
    var contentType = "application/x-www-form-urlencoded";
    if (settings.contentType)
    contentType = settings.contentType;
    // by default the request is done through GET
    var type = "GET";
    if(settings.type)
    type = settings.type;
    // by default there are no parameters sent
    var data = null;
    if(settings.data)
    {
    data = settings.data;
    // if we go through GET we properly adjust the URL
    if(type == "GET")
    url = url + "?" + data;
    }
    // by default the postback is asynchronous
    var async = true;
    if(settings.async)
    async = settings.async;
    // by default we show all the infrastructure errors
    var showErrors = true;
    if(settings.showErrors)
    showErrors = settings.showErrors;
    // create the XmlHttpRequest object
    var xhr = XmlHttp.create();
    // set the postback properties
    xhr.open(type, url, async);
    xhr.onreadystatechange = onreadystatechange;
    xhr.setRequestHeader("Content-Type", contentType);
    xhr.send(data);
    // the function that displays errors
    <B>function displayError(message)</B>
    {
    // ignore errors if showErrors is false
    if (showErrors)
    {
    // display error message
    alert("Error encountered: \n" + message);
    }
    }
    // the function that reads the server response
    function readResponse()
    {
    try
    {
    // retrieve the response content type
    var contentType = xhr.getResponseHeader("Content-Type");
    // build the json object if the response has one
    if (contentType == "application/json")
    {
    response = JSON.parse(xhr.responseText);
    }
    // get the DOM element if the response is XML
    else if (contentType == "text/xml")
    {
    response = xhr.responseXml;
    }
    // by default get the response as text
    else
    {
    response = xhr.responseText;
    }
    // call the callback function if any
    if (settings.complete)
    settings.complete (xhr, response, xhr.status);
    }
    catch (e)
    {
    displayError(e.toString());
    }
    }
    // called when the request state changes
    function onreadystatechange()
    {
    // when readyState is 4, we read the server response
    if (xhr.readyState == 4)
    {
    // continue only if HTTP status is "OK"
    if (xhr.status == 200)
    {
    try
    {
    // read the response from the server
    readResponse();
    }
    catch(e)
    {
    // display error message
    displayError(e.toString());
    }
    }
    else
    {
    // display error message
    displayError(xhr.statusText);
    }
    }
    }
    }
    // static method that returns a new XMLHttpRequest object
    XmlHttp.create = function()
    {
    // will store the reference to the XMLHttpRequest object
    var xmlHttp;
    // create the XMLHttpRequest object
    try
    {
    // assume IE7 or newer or other modern browsers
    xmlHttp = new XMLHttpRequest();
    }
    catch(e)
    {
    // assume IE6 or older
    try
    {
    xmlHttp = new ActiveXObject("Microsoft.XMLHttp");
    }
    catch(e) { }
    }
    // return the created object or display an error message
    if (!xmlHttp)
    alert("Error creating the XMLHttpRequest object.");
    else
    return xmlHttp;
    }
    [/code]
  4. To quickly test the functionality of your XmlHttp class, create a new file named xhrtest.html and add the following code to it:

  5. [code lang=”html”]
    <html>
    <head>
    <script type="text/javascript" src="xhr.js"></script>
    </head>
    <body>
    <div id="test">
    </div>
    <script>
    XmlHttp
    ({url:’async.txt’,
    complete:function(xhr,response,status)
    {
    document.getElementById("test").innerHTML = response;
    }
    });
    </script>
    </body>
    </html>
    [/code]
  6. Now create async.txt with some text in it, and then load http://localhost/ajax/validate/xhrtest.html. Figure 5-6 shows our result:


What just happened?

The code listed above contains significant code from the previous examples and then some new code. Let’s break it down into small pieces and analyze it. The chosen name for our reusable object is XmlHttp. Its functionality is wrapped in two functions:


  • XmlHttp.create(): A static method of the XmlHttp object that creates a XmlHttpRequest object

  • XmlHttp(): The constructor of the XmlHttp object


From a design point of view, the XmlHttp object represents a wrapper around the XmlHttpRequest object. The XmlHttp.create() method contains the same code that we have previously seen in the createXmlHttpRequestObject() method. It simply acts like a factory for an XmlHttpRequest object. The constructor of the XmlHttp object, although it can look quite scary at first sight, actually contains very simple code—provided that you know the theory from Chapter 3, Object Oriented JavaScript. The constructor receives as a parameter a JSON object containing all the settings for the XmlHttp object. Choosing a JSON object is both convenient from the extensibility point of view and easy from the programming point of view. We store the settings in a property with the same name.
[code lang=”java”]
function XmlHttp(settings)
{
// store the settings object in a class property
this.settings = settings;
[/code]
The settings object contains the following properties that will be mainly used for the XmlHttpRequest object:

  • url: The URL of the AJAX request

  • type: The type of the request (GET or POST)

  • contentType : The content type of the request

  • data: The data to be sent to the server

  • async: A fl ag that specifies whether the request is synchronous or asynchronous

  • complete: The function called when the request completes

  • showErrors: A fl ag that indicates whether infrastructure errors will be displayed or not


These are the parameters required to make an AJAX request. Even though the structure and the design of this object are simple, it can be easily extended with more advanced features, giving us the fl exibility feature we defined as a goal. The fl exibility offered by JSON objects means we don’t force the user to pass all the properties mentioned above each time the object is created. Instead, we created a
standard set of default values that the user can choose to overwrite when necessary. The next few lines simply implement this logic.
Making a request through GET or POST is different and we take care of it when setting the parameters for the request:
[code lang=”java”]
// by default there are no parameters sent
var data = null;
if(settings.data)
{
data = settings.data;
// if we go through GET we properly adjust the URL
if(type == "GET")
url = url + "?" + data;
}
[/code]
After having all the settings for the AJAX request, we create the XmlHttpRequest and we open it.
[code lang=”java”]
// create the XmlHttpRequest object
var xhr = XmlHttp.create();
// set the postback properties
xhr.open(type, url, async);
[/code]
The next step is to hook to the readystatechange event:
[code lang=”java”]
xhr.onreadystatechange = onreadystatechange;
[/code]
The handler function is a inner function of the constructor and contains the same code as the handleRequestStateChange() method that you already know. Probably the most interesting piece of code is in the response handler. The readResponse() inner function is responsible for handling the response received from the server. It gets the content type of the response and, based on that, it builds the response JSON object or it retrieves the response as an XML element. If no matching content type is found, the raw text of the response is used instead.
[code lang=”java”]
// retrieve the response content type
var contentType = xhr.getResponseHeader("Content-Type");
// build the json object if the response has one
if (contentType == "application/json")
{
response = JSON.parse(xhr.responseText);
}
// get the DOM element if the response is XML
else if (contentType == "text/xml")
{
response = xhr.responseXml;
}
// by default get the response as text
else
{
response = xhr.responseText;
}
[/code]
After gathering the necessary data, the XmlHttp object passes it all to the callback function (settings.complete()) along with the XmlHttp object and the HTTP response code.
[code lang=”java”]
// call the callback function if any
if (settings.complete)
settings.complete (xhr, response, xhr.status);
[/code]
All in all, the next time you need to call a server script asynchronously from a web page, you can count on XmlHttp to do all the dirty work. You just tell it what URL to contact, specifying the necessary parameters, and it fetches the response for you.

AJAX form validation

In the previous chapter, we talked about error handling and database operations. In this chapter, we redesigned the code for making AJAX requests when creating the XmlHttp class. The AJAX form validation application makes use of these techniques. The application contains three pages:


  • One page renders the form to be validated

  • Another page validates the input

  • The third page is displayed if the validation is successful


The application will have a standard structure, composed of these files:

  • index.php: It is the file loaded initially by the user. It contains references to the necessary JavaScript files and makes asynchronous requests for validation to validate.php.

  • index_top.php: It is a helper file loaded by index.php and contains several objects for rendering the HTML form.

  • validate.css: It is the file containing the CSS styles for the application.

  • json2.js: It is the JavaScript file used for handling JSON objects.

  • xhr.js: It is the JavaScript file that contains our XmlHttp object used for making AJAX requests.

  • validate.js: It is the JavaScript file loaded together with index.php on the client side. It makes asynchronous requests to a PHP script called validate.php to perform the AJAX validation.

  • validate.php: It is a PHP script residing on the same server as index.php, and it offers the server-side functionality requested asynchronously by the JavaScript code in index.php.

  • validate.class.php: It is a PHP script that contains a class called Validate, which contains the business logic and database operations to support the functionality of validate.php.

  • config.php: It will be used to store global configuration options for your application, such as database connection data, and so on.

  • error_handler.php: It contains the error-handling mechanism that changes the text of an error message into a human-readable format.

  • allok.php: It is the page to be displayed if the validation is successful.


Bearing all this in mind, it’s time to get to work!

Time for action – AJAX form validation



  1. If you missed the database exercise in Chapter 4, Using PHP and MySQL on the Server, connect to the ajax database and create a table named users with the following code; otherwise, skip to step 3.

  2. [code]
    CREATE TABLE users
    (
    user_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
    user_name VARCHAR(32) NOT NULL,
    PRIMARY KEY (user_id)
    );
    [/code]
  3. Execute the following INSERT commands to populate your users table with some sample data :

  4. [code]
    INSERT INTO users (user_name) VALUES (‘bogdan’);
    INSERT INTO users (user_name) VALUES (‘audra’);
    INSERT INTO users (user_name) VALUES (‘cristian’);
    [/code]
  5. Let’s start writing the code with the presentation tier. We’ll define the styles for our form by creating a file named validate.css, and adding the following code to it:

  6. [code lang=”html”]
    body
    {
    font-family: Arial, Helvetica, sans-serif;
    font-size: 0.8em;
    color: #000000;
    }
    label
    {
    float: left;
    width: 150px;
    font-weight: bold;
    }
    input, select
    {
    margin-bottom: 3px;
    }
    .button
    {
    font-size: 2em;
    }
    .left
    {
    margin-left: 150px;
    }
    .txtFormLegend
    {
    color: #777777;
    font-weight: bold;
    font-size: large;
    }
    .txtSmall
    {
    color: #999999;
    font-size: smaller;
    }
    .hidden
    {
    display: none;
    }
    .error
    {
    display: block;
    margin-left: 150px;
    color: #ff0000;
    }
    [/code]
  7. Now create a new file named index_top.php, and add the following code to it. This script will be loaded from the main page index.php.

  8. [code lang=”html”]
    <?php
    // enable PHP session
    session_start();
    // Build HTML <option> tags
    <B>function buildOptions($options, $selectedOption)</B>
    {
    foreach ($options as $value => $text)
    {
    if ($value == $selectedOption)
    {
    echo ‘<option value="’ . $value .
    ‘" selected="selected">’ . $text . ‘</option>’;
    }
    else
    {
    echo ‘<option value="’ . $value . ‘">’ . $text .
    ‘</option>’;
    }
    }
    }
    // initialize gender options array
    <B>$genderOptions = array("0" => "[Select]",</B>
    "1" => "Male",
    "2" => "Female");
    // initialize month options array
    <B>$monthOptions = array("0" => "[Select]",</B>
    "1" => "January",
    "2" => "February",
    "3" => "March",
    "4" => "April",
    "5" => "May",
    "6" => "June",
    "7" => "July",
    "8" => "August",
    "9" => "September",
    "10" => "October",
    "11" => "November",
    "12" => "December");
    // initialize some session variables to prevent PHP throwing
    // Notices
    if (!isset($_SESSION[‘values’]))
    {
    $_SESSION[‘values’][‘txtUsername’] = ”;
    $_SESSION[‘values’][‘txtName’] = ”;
    $_SESSION[‘values’][‘selGender’] = ”;
    $_SESSION[‘values’][‘selBthMonth’] = ”;
    $_SESSION[‘values’][‘txtBthDay’] = ”;
    $_SESSION[‘values’][‘txtBthYear’] = ”;
    $_SESSION[‘values’][‘txtEmail’] = ”;
    $_SESSION[‘values’][‘txtPhone’] = ”;
    $_SESSION[‘values’][‘chkReadTerms’] = ”;
    }
    if (!isset($_SESSION[‘errors’]))
    {
    $_SESSION[‘errors’][‘txtUsername’] = ‘hidden’;
    $_SESSION[‘errors’][‘txtName’] = ‘hidden’;
    $_SESSION[‘errors’][‘selGender’] = ‘hidden’;
    $_SESSION[‘errors’][‘selBthMonth’] = ‘hidden’;
    $_SESSION[‘errors’][‘txtBthDay’] = ‘hidden’;
    $_SESSION[‘errors’][‘txtBthYear’] = ‘hidden’;
    $_SESSION[‘errors’][‘txtEmail’] = ‘hidden’;
    $_SESSION[‘errors’][‘txtPhone’] = ‘hidden’;
    $_SESSION[‘errors’][‘chkReadTerms’] = ‘hidden’;
    }
    ?>
    [/code]
  9. Now create index.php, and add the following code to it:

  10. [code lang=”html”]
    <?php
    require_once (‘index_top.php’);
    ?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.
    w3.org/TR/xhtml11/DTD/xhtml11.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <title>Degradable AJAX Form Validation with PHP and
    MySQL</title>
    <meta http-equiv="Content-Type" content="text/html;
    charset=utf-8" />
    <link href="validate.css" rel="stylesheet" type="text/css" />
    </head>
    <body onload="setFocus();">
    <script type="text/javascript" src="json2.js"></script>
    <script type="text/javascript" src="xhr.js"></script>
    <script type="text/javascript" src="validate.js"></script>
    <fieldset>
    <legend class="txtFormLegend">
    New User Registratio Form
    </legend>
    <br />
    <form name="frmRegistration" method="post"
    action="validate.php">
    <input type="hidden" name="validationType" value="php"/>
    <!– Username –>
    <label for="txtUsername">Desired username:</label>
    <input id="txtUsername" name="txtUsername" type="text"
    onblur="validate(this.value, this.id)"
    value="<?php echo $_SESSION[‘values’]
    [‘txtUsername’] ?>" />
    <span id="txtUsernameFailed"
    class="<?php echo $_SESSION[‘errors’][‘txtUsername’]
    ?>">
    This username is in use, or empty username field.
    </span>
    <br />
    <!– Name –>
    <label for="txtName">Your name:</label>
    <input id="txtName" name="txtName" type="text"
    onblur="validate(this.value, this.id)"
    value="<?php echo $_SESSION[‘values’][‘txtName’]
    ?>" />
    <span id="txtNameFailed"
    class="<?php echo $_SESSION[‘errors’][‘txtName’]?>">
    Please enter your name.
    </span>
    <br />
    <!– Gender –>
    <label for="selGender">Gender:</label>
    <select name="selGender" id="selGender"
    onblur="validate(this.value, this.id)">
    <?php buildOptions($genderOptions,
    $_SESSION[‘values’][‘selGender’]); ?>
    </select>
    <span id="selGenderFailed"
    class="<?php echo $_SESSION[‘errors’][‘selGender’]
    ?>">
    Please select your gender.
    </span>
    <br />
    <!– Birthday –>
    <label for="selBthMonth">Birthday:</label>
    <!– Month –>
    <select name="selBthMonth" id="selBthMonth"
    onblur="validate(this.value, this.id)">
    <?php buildOptions($monthOptions,
    $_SESSION[‘values’][‘selBthMonth’]);
    ?>
    </select>
    &nbsp;-&nbsp;
    <!– Day –>
    <input type="text" name="txtBthDay" id="txtBthDay"
    maxlength="2" size="2"
    onblur="validate(this.value, this.id)"
    value="<?php echo $_SESSION[‘values’][‘txtBthDay’]
    ?>" />
    &nbsp;-&nbsp;
    <!– Year –>
    <input type="text" name="txtBthYear" id="txtBthYear"
    maxlength="4" size="2"
    onblur="validate(document.getElementById
    (‘selBthMonth’).options[document.getElementById
    (‘selBthMonth’).selectedIndex].value +
    ‘#’ + document.getElementById(‘txtBthDay’).value +
    ‘#’ + this.value, this.id)"
    value="<?php echo $_SESSION[‘values’][‘txtBthYear’]
    ?>"
    />
    <!– Month, Day, Year validation –>
    <span id="selBthMonthFailed"
    class="<?php echo $_SESSION[‘errors’][‘selBthMonth’]
    ?>">
    Please select your birth month.
    </span>
    <span id="txtBthDayFailed"
    class="<?php echo $_SESSION[‘errors’][‘txtBthDay’]
    ?>">
    Please enter your birth day.
    </span>
    <span id="txtBthYearFailed"
    class="<?php echo $_SESSION[‘errors’][‘txtBthYear’]
    ?>">
    Please enter a valid date.
    </span>
    <br />
    <!– Email –>
    <label for="txtEmail">E-mail:</label>
    <input id="txtEmail" name="txtEmail" type="text"
    onblur="validate(this.value, this.id)"
    value="<?php echo $_SESSION[‘values’][‘txtEmail’]
    ?>" />
    <span id="txtEmailFailed"
    class="<?php echo $_SESSION[‘errors’][‘txtEmail’]
    ?>">
    Invalid e-mail address.
    </span>
    <br />
    <!– Phone number –>
    <label for="txtPhone">Phone number:</label>
    <input id="txtPhone" name="txtPhone" type="text"
    onblur="validate(this.value, this.id)"
    value="<?php echo $_SESSION[‘values’][‘txtPhone’]
    ?>" />
    <span id="txtPhoneFailed"
    class="<?php echo $_SESSION[‘errors’][‘txtPhone’]
    ?>">
    Please insert a valid US phone number (xxx-xxx-xxxx).
    </span>
    <br />
    <!– Read terms checkbox –>
    <input type="checkbox" id="chkReadTerms"
    name="chkReadTerms" class="left"
    onblur="validate(this.checked, this.id)"
    <?php if ($_SESSION[‘values’][‘chkReadTerms’] ==
    ‘on’) echo ‘checked="checked"’ ?> />
    I’ve read the Terms of Use
    <span id="chkReadTermsFailed"
    class="<?php echo$_SESSION[‘errors’]
    [‘chkReadTerms’] ?>">
    Please make sure you read the Terms of Use.
    </span>
    <!– End of form –>
    <hr />
    <span class="txtSmall">Note: All fields arerequired.
    </span>
    <br /><br />
    <input type="submit" name="submitbutton" value="Register"
    class="left button" />
    </form>
    </fieldset>
    </body>
    </html>
    [/code]
  11. Create a new file named allok.php, and add the following code to it:

  12. [code lang=”html”]
    <?php
    // clear any data saved in the session
    session_start();
    session_destroy();
    ?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <title><b>AJAX</b> Form Validation</title>
    <meta http-equiv="Content-Type" content="text/html;
    charset=utf-8" />
    <link href="validate.css" rel="stylesheet" type="text/css" />
    </head>
    <body>
    Registration Successful!<br />
    <a href="index.php" title="Go back"><< Go back</a>
    </body>
    </html>
    [/code]
  13. Copy json2.js (which you downloaded in a previous exercise from http://json.org/json2.js) to your ajax/validate folder.

  14. Create a file named validate.js. This file performs the client-side functionality, including the AJAX requests:

  15. [code lang=”java”]
    // holds the remote server address
    var serverAddress = "validate.php";
    // when set to true, display detailed error messages
    var showErrors = true;
    // the function handles the validation for any form field
    function validate(inputValue, fieldID)
    {
    // the data to be sent to the server through POST
    var data = "validationType=ajax&inputValue=" + inputValue +
    "&fieldID=" + fieldID;
    // build the settings object for the XmlHttp object
    var settings =
    {
    url: serverAddress,
    type: "POST",
    async: true,
    complete: function (xhr, response, status)
    {
    if (xhr.responseText.indexOf("ERRNO") >= 0
    || xhr.responseText.indexOf("error:") >= 0
    || xhr.responseText.length == 0)
    {
    alert(xhr.responseText.length == 0 ?
    "Server error." : response);
    }
    result = response.result;
    fieldID = response.fieldid;
    // find the HTML element that displays the error
    message = document.getElementById(fieldID + "Failed");
    // show the error or hide the error
    message.className = (result == "0") ? "error" : "hidden";
    },
    data: data,
    showErrors: showErrors
    };
    // make a server request to validate the input data
    var xmlHttp = new XmlHttp(settings);
    }
    // sets focus on the first field of the form
    function setFocus()
    {
    document.getElementById("txtUsername").focus();
    }
    [/code]
  16. Now it’s time to add the server-side logic. Start by creating config.php, with the following code in it:

  17. [code lang=”html”]
    <?php
    // defines database connection data
    define(‘DB_HOST’, ‘localhost’);
    define(‘DB_USER’, ‘ajaxuser’);
    define(‘DB_PASSWORD’, ‘practical’);
    define(‘DB_DATABASE’, ‘ajax’);
    ?>
    [/code]
  18. Now create the error handler code in a file named error_handler.php:

  19. [code lang=”html”]
    <?php
    // set the user error handler method to be error_handler
    set_error_handler(‘error_handler’, E_ALL);
    // error handler function
    function error_handler($errNo, $errStr, $errFile, $errLine)
    {
    // clear any output that has already been generated
    if(ob_get_length()) ob_clean();
    // output the error message
    $error_message = ‘ERRNO: ‘ . $errNo . chr(10) .
    ‘TEXT: ‘ . $errStr . chr(10) .
    ‘LOCATION: ‘ . $errFile .
    ‘, line ‘ . $errLine;
    echo $error_message;
    // prevent processing any more PHP scripts
    exit;
    }
    ?>
    [/code]
  20. The PHP script that handles the client’s AJAX calls, and also handles the validation on form submit, is validate.php:

  21. [code lang=”html”]
    <?php
    // start PHP session
    session_start();
    // load error handling script and validation class
    require_once (‘error_handler.php’);
    require_once (‘validate.class.php’);
    // Create new validator object
    $validator = new Validate();
    // read validation type (PHP or <b>AJAX</b>?)
    $validationType = ”;
    if (isset($_POST[‘validationType’]))
    {
    $validationType = $_POST[‘validationType’];
    }
    // <b>AJAX</b> validation or PHP validation?
    if ($validationType == ‘php’)
    {
    // PHP validation is performed by the ValidatePHP method,
    //which returns the page the visitor should be redirected to
    //(which is allok.php if all the data is valid, or back to
    //index.php if not)
    header(‘Location:’ . $validator->ValidatePHP());
    }
    else
    {
    // <b>AJAX</b> validation is performed by the Validate<b>AJAX</b> method.
    //The results are used to form a JSON document that is sent
    //back to the client
    $response = array(‘result’ => $validator->Validate<b>AJAX</b>
    ($_POST[‘inputValue’],$_POST[‘fieldID’]),
    ‘fieldid’ => $_POST[‘fieldID’] );
    // generate the response
    if(ob_get_length()) ob_clean();
    header(‘Content-Type: application/json’);
    echo json_encode($response);
    }
    ?>
    [/code]
  22. The class that supports the validation functionality is called Validate, and it is hosted in a script file called validate.class.php, which looks like this:

  23. [code lang=”html”]
    <?php
    // load error handler and database configuration
    require_once (‘config.php’);
    // Class supports AJAX and PHP web form validation
    class Validate
    {
    // stored database connection
    private $mMysqli;
    // constructor opens database connection
    function __construct()
    {
    $this->mMysqli = new mysqli(DB_HOST, DB_USER, DB_PASSWORD,
    DB_DATABASE);
    }
    // destructor closes database connection
    function __destruct()
    {
    $this->mMysqli->close();
    }
    // supports AJAX validation, verifies a single value
    public function ValidateAJAX($inputValue, $fieldID)
    {
    // check which field is being validated and perform
    // validation
    switch($fieldID)
    {
    // Check if the username is valid
    case ‘txtUsername’:
    return $this->validateUserName($inputValue);
    break;
    // Check if the name is valid
    case ‘txtName’:
    return $this->validateName($inputValue);
    break;
    // Check if a gender was selected
    case ‘selGender’:
    return $this->validateGender($inputValue);
    break;
    // Check if birth month is valid
    case ‘selBthMonth’:
    return $this->validateBirthMonth($inputValue);
    break;
    // Check if birth day is valid
    case ‘txtBthDay’:
    return $this->validateBirthDay($inputValue);
    break;
    // Check if birth year is valid
    case ‘txtBthYear’:
    return $this->validateBirthYear($inputValue);
    break;
    // Check if email is valid
    case ‘txtEmail’:
    return $this->validateEmail($inputValue);
    break;
    // Check if phone is valid
    case ‘txtPhone’:
    return $this->validatePhone($inputValue);
    break;
    // Check if "I have read the terms" checkbox has been
    // checked
    case ‘chkReadTerms’:
    return $this->validateReadTerms($inputValue);
    break;
    }
    }
    // validates all form fields on form submit
    public function ValidatePHP()
    {
    // error flag, becomes 1 when errors are found.
    $errorsExist = 0;
    // clears the errors session flag
    if (isset($_SESSION[‘errors’]))
    unset($_SESSION[‘errors’]);
    // By default all fields are considered valid
    $_SESSION[‘errors’][‘txtUsername’] = ‘hidden’;
    $_SESSION[‘errors’][‘txtName’] = ‘hidden’;
    $_SESSION[‘errors’][‘selGender’] = ‘hidden’;
    $_SESSION[‘errors’][‘selBthMonth’] = ‘hidden’;
    $_SESSION[‘errors’][‘txtBthDay’] = ‘hidden’;
    $_SESSION[‘errors’][‘txtBthYear’] = ‘hidden’;
    $_SESSION[‘errors’][‘txtEmail’] = ‘hidden’;
    $_SESSION[‘errors’][‘txtPhone’] = ‘hidden’;
    $_SESSION[‘errors’][‘chkReadTerms’] = ‘hidden’;
    // Validate username
    if (!$this->validateUserName($_POST[‘txtUsername’]))
    {
    $_SESSION[‘errors’][‘txtUsername’] = ‘error’;
    $errorsExist = 1;
    }
    // Validate name
    if (!$this->validateName($_POST[‘txtName’]))
    {
    $_SESSION[‘errors’][‘txtName’] = ‘error’;
    $errorsExist = 1;
    }
    // Validate gender
    if (!$this->validateGender($_POST[‘selGender’]))
    {
    $_SESSION[‘errors’][‘selGender’] = ‘error’;
    $errorsExist = 1;
    }
    // Validate birth month
    if (!$this->validateBirthMonth($_POST[‘selBthMonth’]))
    {
    $_SESSION[‘errors’][‘selBthMonth’] = ‘error’;
    $errorsExist = 1;
    }
    // Validate birth day
    if (!$this->validateBirthDay($_POST[‘txtBthDay’]))
    {
    $_SESSION[‘errors’][‘txtBthDay’] = ‘error’;
    $errorsExist = 1;
    }
    // Validate birth year and date
    if (!$this->validateBirthYear($_POST[‘selBthMonth’] . ‘#’ .
    $_POST[‘txtBthDay’] . ‘#’ .
    $_POST[‘txtBthYear’]))
    {
    $_SESSION[‘errors’][‘txtBthYear’] = ‘error’;
    $errorsExist = 1;
    }
    // Validate email
    if (!$this->validateEmail($_POST[‘txtEmail’]))
    {
    $_SESSION[‘errors’][‘txtEmail’] = ‘error’;
    $errorsExist = 1;
    }
    // Validate phone
    if (!$this->validatePhone($_POST[‘txtPhone’]))
    {
    $_SESSION[‘errors’][‘txtPhone’] = ‘error’;
    $errorsExist = 1;
    }
    // Validate read terms
    if (!isset($_POST[‘chkReadTerms’]) ||
    !$this->validateReadTerms($_POST[‘chkReadTerms’]) {
    $_SESSION[‘errors’][‘chkReadTerms’] = ‘error’;
    $_SESSION[‘values’][‘chkReadTerms’] = ”;
    $errorsExist = 1;
    }
    // If no errors are found, point to a successful validation
    // page
    if ($errorsExist == 0)
    {
    return ‘allok.php’;
    }
    else
    {
    // If errors are found, save current user input
    foreach ($_POST as $key => $value)
    {
    $_SESSION[‘values’][$key] = $_POST[$key];
    }
    return ‘index.php’;
    }
    }
    // validate user name (must be empty, and must not be already
    // registered)
    private function validateUserName($value)
    {
    // trim and escape input value
    $value = $this->mMysqli->real_escape_string(trim($value));
    // empty user name is not valid
    if ($value == null)
    return 0; // not valid
    // check if the username exists in the database
    $query = $this->mMysqli->query(‘SELECT user_name FROM users’
    ‘WHERE user_name="’ .
    $value . ‘"’);
    if ($this->mMysqli->affected_rows > 0)
    return ‘0’; // not valid
    else
    return ‘1’; // valid
    }
    // validate name
    private function validateName($value)
    {
    // trim and escape input value
    $value = trim($value);
    // empty user name is not valid
    if ($value)
    return 1; // valid
    else
    return 0; // not valid
    }
    // validate gender
    private function validateGender($value)
    {
    // user must have a gender
    return ($value == ‘0’) ? 0 : 1;
    }
    // validate birth month
    private function validateBirthMonth($value)
    {
    // month must be non-null, and between 1 and 12
    return ($value == ” || $value > 12 || $value < 1) ? 0 : 1;
    }
    // validate birth day
    private function validateBirthDay($value)
    {
    // day must be non-null, and between 1 and 31
    return ($value == ” || $value > 31 || $value < 1) ? 0 : 1;
    }
    // validate birth year and the whole date
    private function validateBirthYear($value)
    {
    // valid birth year is between 1900 and 2000
    // get whole date (mm#dd#yyyy)
    $date = explode(‘#’, $value);
    // date can’t be valid if there is no day, month, or year
    if (!$date[0]) return 0;
    if (!$date[2] || !is_numeric($date[2])) return 0;
    // check the date
    return (checkdate($date[0], $date[1], $date[2])) ? 1 : 0;
    }
    // validate email
    private function validateEmail($value)
    {
    // valid email formats: *@*.*, *@*.*.*, *.*@*.*, *.*@*.*.*)
    return (!preg_match(‘/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@
    [a-z0-9-]+(\.[a-z0-9-]+)*
    (\.[a-z]{2,3})$/i’, $value)) ? 0 : 1;
    }
    // validate phone
    private function validatePhone($value)
    {
    // valid phone format: ###-###-####
    return (!preg_match(‘/^[0-9]{3}-*[0-9]{3}-*[0-9]{4}$/’,
    $value)) ? 0 : 1;
    }
    // check the user has read the terms of use
    private function validateReadTerms($value)
    {
    // valid value is ‘true’
    return ($value == ‘true’ || $value == ‘on’) ? 1 : 0;
    }
    }
    ?>
    [/code]
  24. Test your script by loading http://localhost/ajax/validate/index.php in a web browser.

What just happened?

The AJAX validation technique allows us to validate form fields and at the same time inform users if there were any validation errors, and the icing on the cake is that we are doing it without interrupting the user’s activity! The client-side validation is combined with a pure server-side PHP validation that takes place when the user clicks on Submit and thereby submits the entire form to the server. Because of two PHP scripts, validate.php and validate.class.php, both validation types are supported at the server. Let’s examine the code, beginning with the script that handles client-side validation, index.php. The client page is not a simple HTML file but, rather, a PHP file; portions of it will be dynamically generated at the server side. In this way, we retain the form field values when the form is submitted and server-side validation fails. Without the server-side PHP code, if the index page is reloaded, all its fields would be empty.
index.php begins by loading a helper script named index_top.php to: start the session by calling session_start(), define some variables and a function that will be used later in index.php, and initialize some session variables ($_SESSION[‘values’] and $_SESSION[‘errors’]) to avoid PHP sending notices about uninitialized variables.
Note the onload event of the body tag in index.php. It calls the setFocus() function defined in validate.js, which places the input cursor in the first field of the form. In index.php, you see the following sequence of code. Later on, we will be using this same code with additional small changes:
[code lang=”html”]
<!– Username –>
<label for="txtUsername">Desired username:</label>
<input id="txtUsername" name="txtUsername" type="text"
onblur="validate(this.value, this.id)"
value="<?php echo $_SESSION[‘values’][‘txtUsername’]
?>" />
<span id="txtUsernameFailed"
class="<?php echo $_SESSION[‘errors’][‘txtUsername’]
?>">
This username is in use, or empty username field.
</span>
<br />
[/code]
This is the code that displays a form field with its corresponding label and displays an error message underneath when validation fails.

In this example, we display an error message right under
the validated field, but you can customize the position
and appearance of these error messages in validate.css
by changing the properties of the error CSS class.

The onblur event of the input element that is generated when the user leaves an input element triggers the validate() JavaScript function with two parameters: the field’s value and the field’s ID (the server script needs to know which field we need to validate and what the input value is). This function will handle AJAX validation, by making an asynchronous HTTP request to the validate.php script.
The value attributes should be empty on the initial page load, but after submitting the form it should hold the input values. We use session variables to save user input on form submit, in case validation fails and the form is re-displayed. The <span> element that follows contains the error message that gets displayed on failed validation. This span is initially hidden using the hidden CSS class, but we change its CSS class into error, if validation fails.
The validate() function inside validate.js, sends an AJAX request to the server by calling validate.php with three parameters—the field’s value, the field’s ID, and AJAX as the validation type. The data to be sent to the server is formatted accordingly.
[code lang=”java”]
// the data to be sent to the server through POST
var data = "validationType=ajax&inputValue=" + inputValue +
"&fieldID=" + fieldID;
[/code]
Before making the AJAX request, we build the JSON settings object to be passed to the XmlHttp constructor function.
[code lang=”java”]
// build the settings object for the XmlHttp object
var settings =
{
url: serverAddress,
type: "POST",
async: true,
complete: function (xhr, response, status)
{
if (xhr.responseText.indexOf("ERRNO") >= 0
|| xhr.responseText.indexOf("error:") >= 0
|| xhr.responseText.length == 0)
{
alert(xhr.responseText.length == 0 ?
"Server error." : response);
}
result = response.result;
fieldID = response.fieldid;
// find the HTML element that displays the error
message = document.getElementById(fieldID + "Failed");
// show the error or hide the error
message.className = (result == "0") ? "error" : "hidden";
},
data: data,
showErrors: showErrors
};
[/code]
As all of the hard work is delegated to XmlHttp, all that’s left for our function to do is to correctly interpret the response. This is where the complete callback function is used to check for any PHP errors handled by the error_handler.php module and, when there is an error, to show the error(s) in a popup message. Next, the validation result is retrieved from the JSON object. If the validation was successful, we change the CSS class of the error message to hidden; if the validation failed, it is set to error. You change the element’s CSS class using its className property. The final step is the construction of an AJAX request using the XmlHttp object and passing the JSON settings object.
The PHP script that handles server-side processing is validate.php. It starts by loading the error handling script (error_handler.php) and the Validate class that handles the data validation (validate.class.php). Then, it looks for a POST variable named validationType. This exists both when an asynchronous request is made and when the form is submitted via a hidden input field.
[code lang=”java”]
// read validation type (PHP or <b>AJAX</b>?)
$validationType = ”;
if (isset($_POST[‘validationType’]))
{
$validationType = $_POST[‘validationType’];
}
[/code]
Then, based on the value of $validationType, we perform either AJAX validation or PHP validation.
[code lang=”html”]
// AJAX validation or PHP validation?
if ($validationType == ‘php’)
{
// PHP validation is performed by the ValidatePHP method, which
..// returns the page the visitor should be redirected to (which is
// allok.php if all the data is valid, or back to index.php if not)
header(‘Location:’ . $validator->ValidatePHP());
}
else
{
// <b>AJAX</b> validation is performed by the Validate<b>AJAX</b> method. The
// results are used to form a JSON object that is sent back to the
// client
$response = array(‘result’ => $validator->Validate<b>AJAX</b>
($_POST[‘inputValue’], $_POST[‘fieldID’]),
‘fieldid’ => $_POST[‘fieldID’] );
// generate the response
if(ob_get_length()) ob_clean();
header(‘Content-Type: application/json’);
echo json_encode($response);
}
?>
[/code]
For classic, server-side validation, we call the validatePHP() method, which returns the name of the page the browser should be redirected to (which will be allok.php if the validation was successful, or index.php if not). The validation results for each field are stored in the session and should it be reloaded; index.php will indicate the fields that didn’t pass the test. In the case of AJAX calls, the server composes a response that specifies if the field is valid. The response is a JSON object that looks like this:
[code lang=”java”]
{"result":"1","fieldid":"txtUsername"}
[/code]
If the result is 0, then txtUsername isn’t valid and it should be marked accordingly. If the result is 1, the field’s value is valid. Next, let’s look into validate.class.php, referenced in validate.php. This is the workhorse of our PHP validation. The class constructor creates a
connection to the database and the destructor closes that connection. We then have two public methods: ValidateAJAX() (AJAX validation) and ValidatePHP() (server-side validation).

PHP constructors and destructors
In PHP, the constructor is implemented as a method named
__construct(), and is executed automatically when you create
new instances of a class. Just as in other programming languages, the
constructors are useful when you have code that initializes various class
members, because you can rely on it always executing as soon as a new
object of the class is created.
At the opposite side of the object life cycle, you have the destructor,
which is a method named __destruct(), and is called automatically
when the object is destroyed. Destructors are very useful for doing
housekeeping work. In most examples, we will close the database
connection in the destructor, ensuring that we don’t leave any database
connections open, consuming unnecessary resources.

AJAX validation requires two parameters, one that holds the value to be validated ($inputValue) and one that holds the form field’s ID ($fieldID). A switch block loads specific validation for each form field. This function will return 0 if validation fails or 1 if validation is successful. The PHP validation function takes no parameters, as it validates the entire form (after form submission). First we initialize the $errorsExist fl ag to 0. Whenever validation fails for a field, this fl ag will be set to 1 and we will know validation has failed. Then we need to make sure that older session variables are unset in order to ensure that older errors are cleared. We then check each form field against a set of custom rules. If validation fails, we raise the fl ag ($errorsExist = 1) and set the session variable that sets the CSS class for error message to error. If, in the end, the $errorsExist fl ag is still set to 0, it means that the entire validation was successful and so it returns the name of the success page, thus redirecting the browser to that page. If errors are found, we save current user input into session variables, which will be used by index.php to fill the form (remember that by default, when loading the page, all fields are empty). This is how we save current user input:
[code lang=”java”]
foreach ($_POST as $key => $value)
{
$_SESSION[‘values’][$key] = $_POST[$key];
}

In other scenarios, you can save these values even if the validation
is successful, so that should the user fill in another form on our site,
say an order form, they can be reused for him.
[/code]
$_POST is an array holding the names and values of all form elements, and it can be walked through with foreach. This means that for each element inside the $_POST array, we create a new element inside the $_SESSION[‘values’] array. There’s nothing special to mention about validate.css. The success page (allok.php) is very simple as well—it just displays a successful submission confirmation belying all the work that’s gone on before it!

also read:

  • DOJO Tutorials
  • jQuery Tutorials

Summary

We saw how to put into practice everything that we had learned so far in JavaScript by building our own flexible, extensible, reusable object for AJAX requests. We demonstrated the application structure that we specified as well. Our intention here wasn’t to build the perfect validation technique but, rather, a working proof of the concept that takes care of user input and ensures its validity.
This validation technique isn’t possible with JavaScript alone, nor would you want to wait for the fields to be validated only on form submit. Now that we’ve finished a complete, quite complex case study, it’s time to have a quick look at some useful tools that we can use to debug and profile our AJAX code.

Filed Under: AJAX Tagged With: PHP

CF AJAX Programming

November 23, 2009 by itadmin Leave a Comment

ColdFusion 8 Developer Tutorial

Adobe ColdFusion is an application server, renowned for rapid development of dynamic websites, with a straightforward language (CFML), powerful methods for packaging and reusing your code, and AJAX support that will get developers deep into powerful web applications quickly.
This book is the most intense guide to creating professional ColdFusion applications available. Packed with example code, and written in a friendly, easy-to-read style, this book is just want you need if you are serious about ColdFusion. This book will give you clear, concise and, of course, practical guidance to take you from the basics of ColdFusion 8 to the skills that will make you a ColdFusion developer to be reckoned with.

also read:

  • HTML Tutorials
  • CSS Tutorials
  • JavaScript Tutorials

ColdFusion expert John Farrar will teach you about the basics of ColdFusion programming, application architecture, and object reuse, before showing you a range of topics including AJAX library integration, RESTful Web Services, PDF creation and manipulation, and dynamically generated presentation files that will make you the toast of your ColdFusion developer town.
This book digs deep with the basics, with real-world examples of the how and whys, to get more done faster with ColdFusion 8. This book also covers the new features of ColdFusion 8 Update 1.

What This Book Covers

Chapter 1 describes how to enhance basic HTML pages with the power and simplicity of ColdFusion. It also explains the difference between static HTML pages and dynamic ColdFusion pages.
Chapter 2 describes how to create object classes and instantiate object instances. It also describes the object constructors. This chapter explains how to connect to a database through the internal methods of our objects.
Chapter 3 helps us in understanding how to manage multiple products through common forms for listing, editing, and adding data. This chapter explains integrating and streamlining the workflow of web forms and CFC database processing.
In Chapter 4, we will learn how to use the web server memory to create engaging and interactive web applications by using variable scopes. We will also learn how to share some information, and how to protect the rest of the information in a controlled manner. In Chapter 5, we will learn about the basics of custom tags. We will also learn how to integrate cfinclude for libraries of segments. This chapter also includes skinning a website by using custom tags, the use of nested tags, and so on.
Chapter 6 includes wrapping of the ThickBox gallery functions into a custom tag for simple functional reuse and wrapping of a Google map library into our code with a custom tag for simplified interactive maps. This chapter helps us in understanding how to create a multi-state form list wrapped in a custom tag.
In Chapter 7, we will see how to use the authentication that comes standard with CF. This chapter explains how to control the site content based on current user permissions.
In Chapter 8, we will see how AJAX is different from HTML and regular server-oriented web pages. This chapter includes the comparison of HTML, server, and browser technology sites. It also explains about the ColdFusion widgets.
In Chapter 9, we will see the benefit received from the combined power of tag-based encapsulation with AJAX functionality.
Chapter 10 explains about binding, proxy connections, JSON features, Spry data integration, and debugging.
In Chapter 11, we will have a look at the different ways in which we can reorganize pages of PDF documents into a new PDF file from one or more separate PDF source documents.
Chapter 12 explains how to create Verity search collections, how to initialize the Verity indexes, how to interface with the indexes. This chapter also explains how to interface with PDF content for more control when calling documents.
Chapter 13 discusses files, emails, and images. This chapter helps in understanding how some of the common ColdFusion features empower developers to shift the web pages to web applications in many ways.
In Chapter 14, we will learn how to interact with other web servers and create features on our site that will allow others to interact with us.
Chapter 15 gives a broad introduction to ColdFusion’s way of generating dynamic reports. This chapter also gives a brief introduction to the ColdFusion Report Builder tool.
Chapter 16 shows the unique presentation capabilities built into ColdFusion. It gives practical examples to help build custom presentations with dynamic content on demand. Appendix A covers some important details of setting up a development environment. It
also includes some important tips for better productivity.
Appendix B includes some links and resources that are aimed at giving us a good starting base of information. It also explains a group of libaries that prove to be very significant.

CF AJAX Programming

This chapter deals with AJAX programming in ColdFusion. ColdFusion acts a great platform not just because of its code features, but because of its characteristics as to how the code interacts with other features. ColdFusion is a language with depth and power. Yet, as we developers know, it seems real power always requires a bit of custom code. In this chapter, we will have a look at the following topics:


  • Binding

  • Proxy connections

  • JSON features

  • Spry data integration

  • Debugging

Binding

When it comes to programming, the two most commonly used features are CFAJAXProxy and binding. The binding feature allows us to bind or tie things together by using a simpler technique than we would otherwise have needed to create. Binding acts as a double-ended connector in some scenarios. You can set the bind to pull data from another ColdFusion tag on the form. These must be AJAX tags with binding abilities.
There are four forms of bindings, on page, CFC, JavaScript, and URL. Let’s work through each style so that we will understand them well. We will start with on page binding. Remember that the tag has to support the binding. This is not a general ColdFusion feature, but we can use it wherever we desire.

On Page Binding

We are going to bind ‘cfdiv’ to pull its content to show on page binding. We will set the value of a text input to the div. Refer to the following code. ColdFusion AJAX elements work in a manner different from how AJAX is written traditionally. It is more customary to name our browser-side HTML elements with id attributes. This is not the case with the binding features. As we can see in our code example, we have used the name attribute. We should remember to be case sensitive, since this is managed by JavaScript. When we run the code, we will notice that we must leave the input field before the browser registers that there has been a change in the value of the field. This is how the event model for the browser DOM works.
[code lang=”html”]
&lt;cfform id=&quot;myForm&quot; format=&quot;html&quot;&gt;
This is my edit box.&lt;br /&gt;
&lt;cfinput type=&quot;text&quot; name=&quot;myText&quot;&gt;
&lt;/cfform&gt;
&lt;hr /&gt;
And this is the bound div container.&lt;br /&gt;
&lt;cfdiv bind=&quot;{myText}&quot;&gt;&lt;/cfdiv&gt;
[/code]
Notice how we use curly brackets to bind the value of the ‘myText’ input box. This inserts the contents into ‘div’ when the text box loses focus.

This is an example of binding to in-page elements. If the binding we use is tied to a hidden window or tab, then the contents may not be updated.

CFC Binding

Now, we are going to bind our div to a CFC method. We will take the data that was being posted directly to the object, and then we will pass it out to the CFC. The CFC is going to repackage it, and send it back to the browser. The binding will enable the modified version of the content to be sent to the div. Refer to the following CFC code:
[code lang=”html”]
&lt;cfcomponent output=&quot;false&quot;&gt;
&lt;cffunction name=&quot;getDivContent&quot; returntype=&quot;string&quot;
access=&quot;remote&quot;&gt;
&lt;cfargument name=&quot;edit&quot;&gt;
&lt;cfreturn &quot;This is the content returned from the CFC for
the div, the calling page variable is ‘&lt;strong&gt;#arguments.edit#&lt;/
strong&gt;’.&quot;&gt;
&lt;/cffunction&gt;
&lt;/cfcomponent&gt;
[/code]
From the previous code, we can see that the CFC only accepts the argument and passes it back. This could have even returned an image HTML segment with something like a user picture. The following code shows the new page code modifications.
[code lang=”html”]
&lt;cfform id=&quot;myForm&quot; format=&quot;html&quot;&gt;
This is my edit box.&lt;br /&gt;
&lt;cfinput type=&quot;text&quot; name=&quot;myText&quot;&gt;
&lt;/cfform&gt;
&lt;hr /&gt;
And this is the bound div container.&lt;br /&gt;
&lt;cfdiv bind=&quot;cfc:bindsource.getDivContent({myText})&quot;&gt;&lt;/cfdiv&gt;
[/code]
The only change lies in how we bind the cfdiv element tag. Here, you can see that it starts with CFC. Next, it calls bindsource, which is the name of a local CFC. This tells ColdFusion to wire up the browser page, so it will connect to the CFC and things will work as we want. You can observe that inside the method, we are passing the bound variable to the method. When the input field changes by losing focus, the
browser sends a new request to the CFC and updates the div. We need to have the same number of parameters going to the CFC as the number of arguments in our CFC method. We should also make sure that the method has its access method set to remote. Here we can see an example results page.

It is valid to pass the name of the CFC method argument with the data value. This can prevent exceptions caused by not pairing the data in the same order as the method arguments. The last line of the previous code can be modified as follows:
[code lang=”html”]
&lt;cfdiv bind=&quot;cfc:bindsource.getDivContent(edit:{myText})&quot;&gt;&lt;/cfdiv&gt;
[/code]

JavaScript Binding

Now, we will see how simple power can be managed on the browser. We will create a standard JavaScript function and pass the same bound data field through the function. Whenever we update the text box and it looses focus, the contents of the div will be updated from the function on the page. It is suggested that we include all JavaScript rather than put it directly on the page. Refer to the following code:
[code lang=”html”]
&lt;cfform id=&quot;myForm&quot; format=&quot;html&quot;&gt;
This is my edit box.&lt;br /&gt;
&lt;cfinput type=&quot;text&quot; name=&quot;myText&quot;&gt;
&lt;/cfform&gt;
&lt;hr /&gt;
And this is the bound div container.&lt;br /&gt;
&lt;cfdiv bind=&quot;javascript:updateDiv({myText})&quot;&gt;&lt;/cfdiv&gt;
&lt;script&gt;
updateDiv = function(myEdit){
return ‘This is the result that came from the JavaScript function
with the edit box sending &quot;&lt;strong&gt;’+myEdit+’&lt;/strong&gt;&quot;’;
}
&lt;/script&gt;
[/code]
Here is the result of placing the same text into our JavaScript example.

URL Binding

We can achieve the same results by calling a web address. We can actually call a static HTML page. Now, we will call a .cfm page to see the results of changing the text box refl ected back, as for CFC and JavaScript. Here is the code for our main page with the URL binding.
[code lang=”html”]
&lt;cfform id=&quot;myForm&quot; format=&quot;html&quot;&gt;
This is my edit box.&lt;br /&gt;
&lt;cfinput type=&quot;text&quot; name=&quot;myText&quot;&gt;
&lt;/cfform&gt;
&lt;hr /&gt;
And this is the bound div container.&lt;br /&gt;
&lt;cfdiv bind=&quot;url:bindsource.cfm?myEdit={myText}&quot;&gt;&lt;/cfdiv&gt;
[/code]
In the above code, we can see that the binding type is set to URL. Earlier, we used the CFC method bound to a file named bindsource.cfc. Now, we will bind through the URL to a .cfm file. The bound myText data will work in a manner similar to the other cases. It will be sent to the target; in this case, it is a regular server-side page. We require only one line. In this example, our variables are URL variables. Here is the handler page code:
[code lang=”html”]
&lt;cfoutput&gt;
‘This is the result that came from the server page with the edit
box sending &quot;&lt;strong&gt;#url.myEdit#&lt;/strong&gt;&quot;’
&lt;/cfoutput&gt;
[/code]

This tells us that if there is no prefix to the browse request on the bind attribute of the <cfdiv> tag, then it will only work with on-page elements. If we prefix it, then we can pass the data through a CFC, a URL, or through a JavaScript function present on the same page. If we bind to a variable present on the same page, then whenever the bound element updates, the binding will be executed.

Bind with Event

One of t he features of binding that we might overlook its binding based on an event. In the previous examples, we mentioned that the normal event trigger for binding took place when the bound field lost its focus. The following example shows a bind that occurs when the key is released.
[code lang=”html”]
&lt;cfform id=&quot;myForm&quot; format=&quot;html&quot;&gt;
This is my edit box.&lt;br /&gt;
&lt;cfinput type=&quot;text&quot; name=&quot;myText&quot;&gt;
&lt;/cfform&gt;
&lt;hr /&gt;
And this is the bound div container.&lt;br /&gt;
&lt;cfdiv bind=&quot;{myText@keyup}&quot;&gt;&lt;/cfdiv&gt;
[/code]
This is similar to our first example, with the only difference being that the contents of the div are updated as each key is pressed. This works in a manner similar to CFC, JavaScript, and URL bindings. We might also consider binding other elements on a click event, such as a radio button. The following example shows another feature. We can pass any DOM attribute by putting that as an item after the element id. It must be placed before the @ symbol, if you are using a particular event. In this code, we change the input in order to have a class in which we can pass the value of the class attribute and change the binding attribute of the cfdiv element.
[code lang=”html”]
&lt;cfform id=&quot;myForm&quot; format=&quot;html&quot;&gt;
This is my edit box.&lt;br /&gt;
&lt;cfinput type=&quot;text&quot; name=&quot;myText&quot; class=&quot;test&quot;&gt;
&lt;/cfform&gt;
&lt;hr /&gt;
And this is the bound div container.&lt;br /&gt;
&lt;cfdiv bind=&quot;{myText.class@keyup}.{myText}&quot;&gt;&lt;/cfdiv&gt;
[/code]
Here is a list of the events that we can bind.


  • @click

  • @keyup

  • @mousedown

  • @none


The @none event is used for grids and trees, so that changes don’t trigger bind events.

Extra Binding Notes

If you h ave an ID on your CFForm element, then you can refer to the form element based on the container form. The following example helps us to understand
this better.
[code lang=”html”]
Bind = &quot;url:bindsource.cfm?myEdit={myForm:myText}&quot;
[/code]
The ColdFusion 8 documents give the following guides in order to specify the binding expressions.


  1. cfc: componentPath.functionName (parameters)

    The component path cannot use a mapping. The componentPath value
    must be a dot-delimited path from the web root or the directory that
    contains the page.


  2. javascript: functionName (parameters)

  3. url: URL?parameters

  4. ULR?parameters

  5. A string containing one or more instances of {bind parmeter}, such as {firstname}.{lastname}@{domain}


The following table represents the supported formats based on attributes and tags:

Multiple Radio Buttons or Check Boxes and Multiple Select

We can also do binding of multiple radio buttons or check boxes. This is done by giving the same name attribute to the radio button collection or to the check box. We can use unique IDs to allow the use of the HTML <label></label> tags for extending the selection to the contents of for tags, based on the usage of the matching ID of the check boxes or radio buttons. In HTML, the use of a for tag would appear like the following, thus making the user interface better.
[code lang=”html”]
&lt;label for=’firstRadio’&gt;
&lt;input id=’firstRadio’ value=’1′ type=’radio’&gt;
&lt;/label&gt;
[/code]
When we have check boxes or multiple select, the results of the bind are treated like a list. If more than one item is selected, they are stored by separating them with commas similar to any other returning form data.

Spry Binding

Spry is an independent AJAX library that works with the browser DOM. Spry uses the same curly bracket type of parameters for binding. There are some differences in implementation though. Another thing that you can bind to your forms is the Spry data in what is called a Spry dataset. You would do that as shown in this example:
[code lang=”html”]
{spryDataset.dataField}
[/code]
If we wish to bind deeper into a Spry dataset in more detail, we can use standard Spry dataset notation to refer to the data.

To include a literal brace character in a bind expression, excape the character with a backslash.

CFAJAXProxy

This is another very popular AJAX programming feature. This tag allows us to bind AJAX component changes to CFCs, JavaScript, and URLs without the requirement of an AJAX component to pass through it. It also allows us to interact with CFCs directly from JavaScript without binding to any other AJAX component. The JavaScript interface is created for us, and we can reuse the CFC as if it was present locally inside the browser JavaScript. It is very simple and acts as a good solution. Let’s take a look at how it works.

CFAJAX Proxy Binding

We are going to build two text boxes that do arithmetic. The application only adds or subtracts. The first line of our code binds to the radio button set with the name calcType. We will bind to the click event. When either of the buttons is clicked, the call is made to the JavaScript function doCalc() passing the value of the radio button selected. Then the JavaScript function extracts the values of the two boxes and makes sure that they are fl oating-point numbers. If we didn’t convert them, it would see them as text, and append the first text item to the second text item, or we would get some sort of error in subtraction. Then the results are stored and displayed with the alert function.
[code lang=”html”]
&lt;cfajaxproxy bind=&quot;javascript:doCalc({calcType@click})&quot;&gt;
&lt;cfform id=&quot;myForm&quot; format=&quot;html&quot;&gt;
Enter Two Numbers.&lt;br /&gt;
&lt;cfinput type=&quot;text&quot; name=&quot;number1&quot; id=&quot;number1&quot;&gt;&lt;br /&gt;
&lt;cfinput type=&quot;text&quot; name=&quot;number2&quot; id=&quot;number2&quot;&gt;&lt;br /&gt;
&lt;label for=&quot;calcAdd&quot;&gt;
&lt;cfinput type=&quot;radio&quot; value=&quot;add&quot;
name=&quot;calcType&quot; id=&quot;calcAdd&quot;&gt;
Add&lt;/label&gt;&lt;br /&gt;
&lt;label for=&quot;calcSubtract&quot;&gt;
&lt;cfinput type=&quot;radio&quot; value=&quot;subtract&quot;
name=&quot;calcType&quot; id=&quot;calcSubtract&quot;&gt;
Subtract&lt;/label&gt;&lt;br /&gt;
&lt; /cfform&gt;
&lt;script&gt;
doCalc = function(thisCalc){
var myResult = 0;
var number1 = parseFloat(document.getElementById(‘number1’).
value);
var number2 = parseFloat(document.getElementById(‘number2’).
value);
switch(thisCalc){
case ‘add’:
myResult = number1 + number2;
break;
case ‘subtract’:
myResult = number1 – number2;
break;
}
alert(myResult);
}
&lt;/script&gt;
[/code]
This is what we would see if we entered ’23’ and ’11’ and had selected the subtract
radio button:

We could have sent the results to either a CFC or URL as we did earlier. We do not need to have visible results in this example either, but it was just to show what was going on. We can see that one of the uses of CFAJAXProxy is to bind.

CFC Proxy Class Objects

An other use of CFAJAXProxy is to extend the remote methods of a CFC into the currently loaded AJAX page on the browser. This function is not binding, but rather an actual proxy. This means that we will extend the functionality of the remote methods right into the web page without writing extensive code. We will be converting our math webpage to support multiplication and division. We could do this easily in the browser. But we want to show the power of extending CFCs, so we will add these two functions in our CFC and work with them from there.
[code lang=”html”]
&lt;cfajaxproxy bind=&quot;javascript:doCalc({calcType@click})&quot;&gt;
&lt;cfajaxproxy cfc=&quot;serverMath&quot; jsclassname=&quot;remoteMath&quot;&gt;
&lt;cfform id=&quot;myForm&quot; format=&quot;html&quot;&gt;
Enter Two Numbers.&lt;br /&gt;
&lt;cfinput type=&quot;text&quot; name=&quot;number1&quot; id=&quot;number1&quot;&gt;&lt;br /&gt;
&lt;cfinput type=&quot;text&quot; name=&quot;number2&quot; id=&quot;number2&quot;&gt;&lt;br /&gt;
&lt;label for=&quot;calcAdd&quot;&gt;
&lt;cfinput type=&quot;radio&quot; value=&quot;add&quot;
name=&quot;calcType&quot; id=&quot;calcAdd&quot;&gt;
Add&lt;/label&gt;&lt;br /&gt;
&lt;label for=&quot;calcSubtract&quot;&gt;
&lt;cfinput type=&quot;radio&quot; value=&quot;subtract&quot;
name=&quot;calcType&quot; id=&quot;calcSubtract&quot;&gt;
Subtract&lt;/label&gt;&lt;br /&gt;
&lt;label for=&quot;calcMultiply&quot;&gt;
&lt;cfinput type=&quot;radio&quot; value=&quot;multiply&quot;
name=&quot;calcType&quot; id=&quot;calcMultiply&quot;&gt;
Multiply&lt;/label&gt;&lt;br /&gt;
&lt;label for=&quot;calcDivide&quot;&gt;
&lt;cfinput type=&quot;radio&quot; value=&quot;divide&quot;
name=&quot;calcType&quot; id=&quot;calcDivide&quot;&gt;
Divide&lt;/label&gt;&lt;br /&gt;
&lt;/cfform&gt;
&lt;script&gt;
jsMath = new remoteMath();
doCalc = function(thisCalc){
var myResult = 0;
var number1 = parseFloat(document.getElementById(‘number1’).
value);
var number2 = parseFloat(document.getElementById(‘number2’).
value);
switch(thisCalc){
case ‘add’:
myResult = number1 + number2;
break;
case ‘subtract’:
myResult = number1 – number2;
break;
case ‘multiply’:
myResult = jsMath.doMultiply(number1,number2);
break;
case ‘divide’:
myResult = jsMath.doDivide(number1,number2);
break;
}
alert(myResult);
}
&lt;/script&gt;
[/code]
The first modification to our code is to use the CFAJAXProxy tag in order to generate a proxy connection to the remote CFC component. We use an alias name of remoteMath for this component. This becomes a JavaScript class that helps in creating a local object that proxies between this page and our CFC. We then add two more radio buttons so that we have an interface for doing the multiplication function and the division function in our example. The next new line is where we create an object called jsMath in this example. This is not actually JavaScript math, but a JavaScript object that uses the remoteMath class to build an object for communicating with the CFC. Lastly, we check the value of the selected radio button. Then we use our jsMath object, and communicate with the remote server. The name of the remote method is the same as we use on our object and then we pass the argument parameters to the server. The return value is put in our myResult variable just as we did from JavaScript in add and subtract. If we use the same numbers and click Divide, the following result will be obtained. Here is the screenshot of the page in action and the CFC code.

[code lang=”html”]
&lt;cfcomponent output=&quot;false&quot;&gt;
&lt;cffunction name=&quot;doDivide&quot; access=&quot;remote&quot;&gt;
&lt;cfargument name=&quot;number1&quot;&gt;
&lt;cfargument name=&quot;number2&quot;&gt;
&lt;cfreturn arguments.number1 / arguments.number2&gt;
&lt;/cffunction&gt;
&lt;cffunction name=&quot;doMultiply&quot; access=&quot;remote&quot;&gt;
&lt;cfargument name=&quot;number1&quot;&gt;
&lt;cfargument name=&quot;number2&quot;&gt;
&lt;cfreturn arguments.number1 * arguments.number2&gt;
&lt;/cffunction&gt;
&lt;/cfcomponent&gt;
[/code]
Now in a real-world application, we might be looking for some data or updating a database if we were doing this type of proxy function interaction. The point is that all the coupling and AJAXing is done with little code. It is truly a remarkable work as the Adobe engineers have worked hard for this connectivity. This is how ColdFusion has become better than ever before!
One thing that we have not yet dealt with is the callback functions. There are two standard types of callback object methods in remote CFC proxy classes, the setCallbackHandler() method and the setErrorHandler() method. We are going to modify our code so that the results are automatically sent to these handlers with our CFC interaction. Here is the final code for our examples.
[code lang=”html”]
&lt;cf ajaxproxy bind=&quot;javascript:doCalc({calcType@click})&quot;&gt;
&lt;cfajaxproxy cfc=&quot;serverMath&quot; jsclassname=&quot;remoteMath&quot;&gt;
&lt;cfform id=&quot;myForm&quot; format=&quot;html&quot;&gt;
Enter Two Numbers.&lt;br /&gt;
&lt;cfinput type=&quot;text&quot; name=&quot;number1&quot; id=&quot;number1&quot;&gt;&lt;br /&gt;
&lt;cfinput type=&quot;text&quot; name=&quot;number2&quot; id=&quot;number2&quot;&gt;&lt;br /&gt;
&lt;label for=&quot;calcAdd&quot;&gt;
&lt;cfinput type=&quot;radio&quot; value=&quot;add&quot;
name=&quot;calcType&quot; id=&quot;calcAdd&quot;&gt;
Add&lt;/label&gt;&lt;br /&gt;
&lt;label for=&quot;calcSubtract&quot;&gt;
&lt;cfinput type=&quot;radio&quot; value=&quot;subtract&quot;
name=&quot;calcType&quot; id=&quot;calcSubtract&quot;&gt;
Subtract&lt;/label&gt;&lt;br /&gt;
&lt;label for=&quot;calcMultiply&quot;&gt;
&lt;cfinput type=&quot;radio&quot; value=&quot;multiply&quot;
name=&quot;calcType&quot; id=&quot;calcMultiply&quot;&gt;
Multiply&lt;/label&gt;&lt;br /&gt;
&lt;label for=&quot;calcDivide&quot;&gt;
&lt;cfinput type=&quot;radio&quot; value=&quot;divide&quot;
name=&quot;calcType&quot; id=&quot;calcDivide&quot;&gt;
Divide&lt;/label&gt;&lt;br /&gt;
&lt;/cfform&gt;
&lt;script&gt;
jsMath = new remoteMath();
doCalc = function(thisCalc){
var number1 = parseFloat(document.getElementById(‘number1’).value);
var number2 = parseFloat(document.getElementById(‘number2’).value);
jsMath.setCallbackHandler(showResult);
jsMath.setErrorHandler(showError);
switch(thisCalc){
case ‘add’:
showResult(number1 + number2);
break;
case ‘subtract’:
showResult(number1 – number2);
break;
case ‘multiply’:
jsMath.doMultiply(number1,number2);
break;
case ‘divide’:
jsMath.doDivide(number1,number2);
break;
}
}
showResult = function(result){
alert(result);
}
showError = function(statusCode,statusMsg){
alert(&quot;status: &quot;+statusCode+&quot;\n&quot;+statusMsg);
}
&lt;/script&gt;
[/code]
We set the callback handers inside our doCalc() function for the jsMath object. These methods are default names in the ColdFusion AJAX plumbing. It should be noted that we do not want to create remote methods with these names in our CFCs. We removed the variable that we were using and have now created another function called showResult() for handling the addition and subtraction. Now, let us look at the multiply case statement block and the divide case statement block for our code. There is no evidence as to how the output from these calls is being handled. This is why we have declared the setCallbackHandler() and setErrorHandler() methods. In those methods, we put the name of the callback handler functions without their parents. This is a standard way to handle the referencing of a callback handler in JavaScript. We can see that the standard parameters are passed to the error handler. Run the modified code and pass in a zero for the bottom number, and
this is what you will see. We could produce much more elaborate code for handling the error. We could pass structured code back to the success method, and do much more there also. We kept this example as simple as possible to help us understand the power and features of how ColdFusion AJAX programming works for both binding and proxy functions.

This handles all the data type conversions between ColdFusion and browser JavaScript variables and structure. This makes ColdFusion the easiest and fastest application for doing AJAX. Also, this platform provides a high level of power and ease to developers.

Client Debugging

There are a number of tools that can make AJAX programming more effective. We will look at Firebug and the built-in debugger that is a part of ColdFusion.

Firebug


One of the best tools available for AJAX development is Firebug. This tool is a plugin for Firefox with many abilities. The one we will look at specifically here is the ability to drill down into the DOM structure of a browser page. We are going to look at how this tool works. First, we will have a look at the previous example and take the radio button for our divide selection. Here is a screenshot of the page in which we run firebug. Refer to http://www.getfirebug.com/ for the features of this plug-in.

We see the Inspect menu item at the top. If we click on it, then we will be able to click on the radio button besides the Divide text. This in turn will give us the following in our console view.

If we then go to the right pane of firebug and click on the DOM item, we will get the structure details of the object. There are several types of objects that are explained in detail in ColdFusion and this gets loaded with AJAX pages. These can be entered by clicking on the Console tab present in the left panel. Then as you can see, you have an entry line at the bottom where you can enter any DOM object name or any JavaScript function, and it will allow us to see what is available with that item. If you’re going to dive deeper into AJAX, these are the tools to make the journey much simpler. If you don’t have a library loaded that supports it, you can still use the common DOM element shortcut. This means that for the radio button above with the id calcDivide, we could use the full DOM of document.getElementById
(calcDivide) or we can use the shortcut version $(‘calcDivide’), and press Enter.

Now, we do n’t see the item within the context of the HTML page. We just see the item we have requested. If we were calling an existing JavaScript structure or a simple value, we would see that too. With a similar item, we can click on it, and then have a look at the DOM model for that particular item as we did earlier. The additional items that the ColdFusion AJAX includes are listed here. We would just
enter them in the prompt line as we did for the radio button ID.

  • ColdFusion.Layout.getBorderLayout (name)

  • ColdFusion.Grid.getGridObject (name)

  • ColdFusion.Layout.getTabLayout (name)

  • ColdFusion.Tree.getTreeObject (name)

  • ColdFusion.Window.getWindowObject (name)


To get more information about these topics, you can look at the ColdFusion documents that consist of EXT and YUI library files. The name of course is the same as you assigned while creating the item. Also, we need to remember that JavaScript is case sensitive.

Built-In Debugging

This is a very useful feature. All you have to do is to change the URL in the address bar to get this working. Now, if you are running ColdFusion on a live site, this feature should be shut off in the ColdFusion Administrator. Here is the URL with and without debugging. The only difference is we have added an extra variable to the URL. Just add it to the last variable after the question mark in the URL.
[code lang=”html”]
http://localhost/cfb/code/chapter_10/bind_7.cfm
http://localhost/cfb/code/chapter_10/bind_7.cfm?cfdebug
[/code]
Here is the screenshot of the debugging window.

We can see that there are a number of features to this debugging window. We can Collapse the window to get it out of the way. It can also be dragged around the screen to move it out of the way, if collapsing is not enough. It is dragged by holding the mouse button down over the dark grey area where the title is. We can toggle to obtain information on the type of debugging. This will also toggle the information that is already present. When we have more information, it will create a scroll bar so as to move through the log. The pause and clear buttons are great features.

Logging Features


Not only is deb ugging built in, but the system is designed to allow us to send logging to the window so that it becomes easier. Let’s open our Firebug console and log the element we were looking at earlier. There are a number of logging features, and it is a better way for managing our build or debugging interaction with the logger.

Here, we observe that we do not get as many details as we used to get in the DOM panel of the Firebug console. Remember that the $() shortcut is a part of Firebug. Normally, you either need to have that in another AJAX library, or you have to use the old method that we mentioned earlier. Here are the types of log functions that are included with the debugger.

  • ColdFusion.Log.dump

  • ColdFusion.Log.debug

  • ColdFusion.Log.error

  • ColdFusion.Log.info


The ColdFusion .Log.dump has a special function whereas the remaining three only change the tag that is before the log item. One thing that can be done is to design custom tags and CFCs, so that they have a ‘test’ mode that can be run. This would allow them to interact with the debugging tools and make a more sustainable product. This would mean there would be more quality assurance for all our software.

Customization


When it comes to coding, there are many things that can be done. This is a two-fold scenario. The primary way to customize is more on design than on coding. If we are inclined, we can actually go as far as replacing all the code of core AJAX functions. Generally, before going that far, it might be a better idea to look at individual libraries and see if there is something present already that can help us achieve
our goals.
We are going to look at another tag in ColdFusion 8 known as <CFAjaxImport/>. Most of the look-and-feel of the AJAX tags is controlled by CSS files. Using this tag, we can substitute custom styles for these tags. This will be coded as in the given example. The cssSrc attribute specifies the URL, relative to the web root of the directory that contains the CSS files used by ColdFusion AJAX features, with
the exception of the rich text editor. This directory must have the same directory structure, and contain the same CSS files, and image files required by the CSS files, as the web_root/CFIDE/scripts/ajax/resources directory.
[code lang=”html”]
&amp;lt;cfAjaxImport cssSrc=&quot;/mySite/myCSS/&quot;&amp;gt;
[/code]
We can also change the scriptSrc attribute. Similar to CSS styles, you need to include structure of the same scripts as found in the /cfide/scripts/ directory. This is where hackers can extend the core power that ships in ColdFusion. If you use this attribute, you will not be able to use it more than once in a request. Another important thing about this tag is the ability to declare the AJAX tags that need modification. As developers, we often forget, as we think about code, the challenge of designing a site to the owner’s satisfaction. We are often negligent in this aspect. The following table shows the tags that can be put in the tag attribute list to set what is modified by the cfAjaxImport tag.

Automatically Wired AJAX Links

This function allows you to connect the links inside a cfdiv, cflayoutarea, cfpod, or cfwindow control to the containing control. This code would load the local file as the content of the container. It will not load a file from a remote site to protect it from cross-site script attacks.
[code lang=”html”]
&lt;cfdiv height=&quot;600&quot; width=&quot;600&quot; name=&quot;ajaxDiv&quot;&gt;
&lt;cfoutput&gt;
&lt;a href=&quot;#AjaxLink(‘LinkOne.cfm’)#&quot;&gt;Link One&lt;/a&gt;
&lt;br /&gt;
&lt;a href=&quot;#AjaxLink(‘LinkTwo.cfm’)#&quot;&gt;Link Two&lt;/a&gt;
&lt;/cfoutput&gt;
&lt;/cfdiv&gt;
[/code]

Execute JavaScript after Loading Content


There are two times when content is loaded. First, when the page is loaded and then when the content within a section such as a cfdiv, cflayoutarea, cfpod, or cfwindow is loaded. You want the browser DOM to be created before any JavaScript is called. This function helps in ensuring that the code isn’t run prematurely. Here is an example of how to run the command when the whole page is loaded.
[code lang=”html”]
&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Enter Mail Login Details&lt;/title&gt;
&lt;script&gt;
init = function() {
ColdFusion.Window.show(‘loginwindow’);
}
&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;cfwindow name=&quot;loginwindow&quot; title=&quot;Enter Login Details&quot;
draggable=&quot;false&quot; closable=&quot;false&quot; resizable=&quot;false&quot;
width=&quot;450&quot; height=&quot;200&quot;&gt;
&lt;cfoutput&gt;
&lt;form action=&quot;#cgi.script_name#&quot; method=&quot;post&quot; name=&quot;loginform&quot;&gt;
&lt;table width=&quot;400&quot; class=&quot;loginTable&quot; cellpadding=&quot;5&quot;&gt;
&lt;tr&gt;
&lt;td&gt;username:&lt;/td&gt;
&lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;username&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;password:&lt;/td&gt;
&lt;td&gt;&lt;input type=&quot;password&quot; name=&quot;password&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;input type=&quot;submit&quot; name=&quot;login&quot; value=&quot;Login&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/form&gt;
&lt;/cfoutput&gt;
&lt;/cfwindow&gt;
&lt;cfoutput&gt;
&lt;form action=&quot;#cgi.script_name#&quot; method=&quot;post&quot; name=&quot;changePasswor
dForm&quot;&gt;
&lt;table width=&quot;400&quot;&gt;
&lt;tr&gt;
&lt;td&gt;old password:&lt;/td&gt;
&lt;td&gt;&lt;input type=&quot;password&quot; name=&quot;password&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;new password:&lt;/td&gt;
&lt;td&gt;&lt;input type=&quot;password&quot; name=&quot;password&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;input type=&quot;submit&quot; name=&quot;login&quot; value=&quot;Login&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/form&gt;
&lt;/cfoutput&gt;
&lt;cfset AjaxOnLoad(&quot;init&quot;)&gt;
&lt;/body&gt;
&lt;/html&gt;
[/code]
This example is a little longer than our previous examples. But it makes sure that the user is logged in before he or she attempts to change a password. It’s not a complete example but is intended to explain in a real-world application how to use the tag for illustration purposes. There are missing pieces. So DO NOT use it as it is!

Other Cool Commands


There are three JSON functions built into ColdFusion. Most of the time, you will find this is used in CF8 AJAX, where it is handled automatically. Yet, if you are working with Yahoo data or sending something to jQuery, then you might require the ability to work with JSON data along with built-in functions. You can dump the results with CFDump on the server side, and with the debugging dump function.

  • JSONencrypt() converts to JavaScript object notation

  • JSONdecrypt() converts from JavaScript object notation

  • isJSON() checks to see if a variable’s content is in a valid JSON format


Spry is an AJAX library created by ADOBE. It does many amazing things. The first time I came across the curly bracket data alias style of coding that we use in ColdFusion AJAX was in Spry. Shortly thereafter, I also found similar practice in ActionScript coding. This may not have been the first time it came to my attention. If we are going to work with Spry AJAX pages, then we need to convert data to Sprybased
data for in-browser usage. The ins and outs of Spry could end up being as much text as we have on CFAJAX, if not more.

  • CFSpryDataset()


Post for CFAJAX Calls


We will complete this chapter with a tip on how to send data to the browser via Post, instead of sending it via standard URL variables. We can send more data through a Post than we can though URL style variables.
[code lang=”html”]
&lt;html&gt;
&lt;head&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
function cfcViaPost()
{
Var pickyObject = new pickyCFC();
pickyObject.setHTTPMethod(&quot;POST&quot;);
pickyObject.doSomething();
}
&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;cfajaxproxy cfc=&quot;pickyCFC&quot;&gt;
&lt;cfinput type=&quot;button&quot; name=&quot;test&quot; onclick=&quot;cfcViaPost();&quot;&gt;
&lt;/body&gt;
&lt;/html&gt;
[/code]

also read:

  • DOJO Tutorials
  • jQuery Tutorials

Summary

It seems to me like there were so many subjects it was hard to tell where to stop. With that said you should think there is still plenty of content that isn’t contained in this chapter. We have covered the following:


  • Binding between object data and container objects

  • Binding between CFCs and container objects

  • Binding between URLs and container objects

  • Binding between JavaScript and container objects

  • How to make binding objects event sensitive

  • Binding on multi-item objects like radio buttons, check boxes or multi-select boxes

  • CFAJAXproxy for binding objects to JavaScript functions

  • CFAJAXproxy to extend connectivity of CFCs to JavaScript class objects

  • Success and Exception Handling on CFC proxy class objects execution

Filed Under: AJAX Tagged With: CF AJAX

  • « Previous Page
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • Next Page »

Follow Us

  • Facebook
  • Pinterest

As a participant in the Amazon Services LLC Associates Program, this site may earn from qualifying purchases. We may also earn commissions on purchases from other retail websites.

JavaBeat

FEATURED TUTORIALS

Answered: Using Java to Convert Int to String

What is new in Java 6.0 Collections API?

The Java 6.0 Compiler API

Copyright © by JavaBeat · All rights reserved