Persisting a Class Across Tables with Hibernate

By Jim White (Instructor and Director of Training at Intertech)

Hibernate is a very versatile framework.  Need to persist a Java object into a relational database?  Hibernate provides a way to map the associated Java class's properties to the database table(s) in just about any way you can imagine.  The idea is that the mapping framework should not constrain how you design your database tables or how you design your Java classes.

Pretty regularly, Java objects are often more fine-grained that the database tables that hold their state.  For example, you might have separate Java Customer and Address objects, but have just a single customer table that stores both customer and address data.  This "denormalization" in the database is often done for increased performance or simplicity (see Hibernate's Core documentation on something called components here).

A few weeks ago, I had a couple of students (thanks Anna and Kartik) ask if it was possible to do the opposite.  That is, is it possible to map a single Java class across multiple tables?  Given Hibernate's versatility and flexibility it is probably not unexpected to learn that it is very much possible – although a little more unusual.  Here is an example to show how this is done.

First, here at two tables (Property and Address) which will hold a single object's (RealEstate) state data.

create table address(
id integer GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY,
street varchar(50),
city varchar(50),
state varchar(50),
zip int
);

create table property(
id integer GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY,
square_footage int,
bedrooms int,
bathrooms int,
agent_name varchar(50)
);

 

Now here is the single class to be mapped to these two tables complete with Hibernate mapping annotations to provide the appropriate mapping.

package com.intertech.domain;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.SecondaryTable;
import javax.persistence.SecondaryTables;
import javax.persistence.Table;

@Entity
@Table(name="Property")
@SecondaryTables({
    @SecondaryTable(name="Address", pkJoinColumns={
        @PrimaryKeyJoinColumn(name="id", referencedColumnName="id")})})
public class RealEstate {
    @Id
    @GeneratedValue()
    private Integer id;
    @Column(table="Address")
    private String street;
    @Column(table="Address")
    private String city;
    @Column(table="Address")
    private String state;
    @Column(table="Address")
    private int zip;
    @Column(name = "square_footage")
    private int squareFootage;
    private int bedrooms;
    private int bathrooms;
    @Column(name = "agent_name")
    private String agentName;

//getters, setters and constructors removed for brevity

}

Importantly, notice the @Table and @SecondaryTables (and @SecondaryTable parameter) annotations that specify the multiple tables to store RealEstate object data.  The id's for both tables must be provided in the @SecondaryTable to indicate how rows in these tables are joined to retrieve the data for any one instance.  Notice also how the properties, like street, that are not stored in the primary table (as identified by the @Table annotation) require the @Column annotation to indicate which secondary table (in this case there is only one – the Address table) holds this state.

If you are interested in this little example code and a small little application that tests storing and retrieving RealEstate objects, you'll find it in a zip file located at Intertech's web site here.

While there are certainly exceptions, if you can dream it you should be able to map it using the Hibernate framework between your Java objects and the relational database.  If you would like to learn more about Hibernate, I would welcome your attendance in our Complete Hibernate class.  Please - come join us!


Posted by: Jim White
Posted on: 3/8/2010 at 12:22 PM
Tags: , ,
Categories: Java
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

Lazy Object Instantiation with .NET 4.0

When you are creating classes, you may occasionally run into a situation where you need to account for a particular member variable in code, which may never actually be needed, in that the object user may not call the method (or property) which makes use of it. Fair enough, however this can be very problematic if the member variable in question requires a large amount of memory to be instantiated. For example, assume you are writing a class that encapsulates the operations of a digital music player. In addition to some expected methods, such as Play(), Pause() and Stop(), you also want to provide the ability to return a collection of Song objects (via a class named AllTracks), which represent every single digital music file on the device. If you wish to follow along, create a new Console Application named LazyObjectInstantiation, and define the following class types:

Code Snippet
  1. // Represents a single song.
  2. class Song
  3. {
  4.     public string Artist { get; set; }
  5.     public string TrackName { get; set; }
  6.     public double TrackLength { get; set; }
  7. }
  8.  
  9. // Represents all songs on a player.
  10. class AllTracks
  11. {
  12.     // Our media player can have a maximum
  13.     // of 10,000 songs.
  14.     private Song[] allSongs = new Song[10000];
  15.  
  16.     public AllTracks()
  17.     {
  18.         // Assume we fill up the array
  19.         // of Song objects here.
  20.         Console.WriteLine("Filling up the songs!");
  21.     }
  22. }
  23.  
  24. // The MediaPlayer has-a AllTracks object.
  25. class MediaPlayer
  26. {
  27.     // Assume these methods do something useful.
  28.     public void Play() { /* Play a song */ }
  29.     public void Pause() { /* Pause the song */ }
  30.     public void Stop() { /* Stop playback */ }
  31.     private AllTracks allSongs = new AllTracks();
  32.     public AllTracks GetAllTracks()
  33.     {
  34.         // Return all of the songs.
  35.         return allSongs;
  36.     }
  37. }

The current implementation of MediaPlayer is making the assumption that the object user will want to obtain a list of songs via the GetAllTracks() method. Well, what if the object user does not need to obtain this list of music? In either case, the AllTracks member variable will create 10,000 Song objects in memory:

Code Snippet
  1. static void Main(string[] args)
  2. {
  3.     // This caller does not care about getting all songs,
  4.     // but indirectly created 10,000 objects!
  5.     MediaPlayer myPlayer = new MediaPlayer();
  6.     myPlayer.Play();
  7. }

Clearly, you would rather not create 10,000 objects that nobody is interested in using, as that will add a good deal of stress to the .NET garbage collector. While you could manually add additional code to ensure the allSongs object is only created if used (perhaps using the factory method design pattern), there is an easier way. With the release of .NET 4.0, the base class libraries provide a very interesting generic class named Lazy<>, defined in the System namespace of mscorlib.dll. This class allows you to define data that will not be created unless your code base actually makes use of it. As this is a generic class, you must specify the type of item to be created on first use, which can be any type with the .NET base class libraries or a custom type you have authored yourself. To enable lazy instantiation of the AllTracks member variable, we can simply replace this:

Code Snippet
  1. class MediaPlayer
  2. {
  3.     private AllTracks allSongs = new AllTracks();
  4. }

with this:

Code Snippet
  1. class MediaPlayer
  2. {
  3.     private Lazy<AllTracks> allSongs = new Lazy<AllTracks>();
  4.  
  5.     public AllTracks GetAllTracks()
  6.     {
  7.         // Return all of the songs.
  8.         return allSongs.Value;
  9.     }
  10. }

Beyond the fact that we are now representing the AllTracks member variable as a Lazy<> type, notice that the implementation of the previous GetAllTracks() method has also been updated. Specifically, we must make use of the read-only Value property of the Lazy<> class to obtain the actual stored data (in this case, the AllTracks object which is maintaining the 10,000 Song objects). With this simple update, notice how the following updated Main() method will indirectly only allocate the Song objects if GetAllTracks() is indeed called:

Code Snippet
  1. static void Main(string[] args)
  2. {
  3.     Console.WriteLine("***** Fun with Lazy Instantiation *****\n");
  4.     // No allocation of AllTracks object here!
  5.     MediaPlayer myPlayer = new MediaPlayer();
  6.     myPlayer.Play();
  7.  
  8.     // Allocation of AllTracks happens when you call GetAllTracks().
  9.     MediaPlayer yourPlayer = new MediaPlayer();
  10.     AllTracks yourMusic = yourPlayer.GetAllTracks();
  11.     Console.ReadLine();
  12. }

Customizing the Creation of the Lazy Data

When you declare a Lazy<> variable, the actual internal data type is created using the default constructor by default:

Code Snippet
  1. // Default constructor of AllTracks is called when the Lazy<>
  2. // variable is used.
  3. private Lazy<AllTracks> allSongs = new Lazy<AllTracks>();

While this might be fine in some cases, what if the AllTracks class had some additional constructors, and you wish to ensure the correct one is called. Furthermore, what if you have some extra work do to (beyond simply creating the AllTracks object) when the Lazy<> variable is made? As luck would have it, the Lazy<> class allows you to specify a generic delegate as an optional parameter, which will specify a method to call during the creation of the wrapped type. The generic delegate in question is of type System.Func<>, which can point to a method that returns the same data type being created by the related Lazy<> variable, and can take up to 16 parameters (which are typed using generic type parameters). In most cases, you will not need to specify any parameters to pass method pointed to by Func<>. Furthermore, to greatly simplify the use of the required Func<>, I'd recommend using a lambda expression (see Chapter 11 for details regarding the delegate / lambda relationship). This all being said, here is a final version of MediaPlayer which adds a bit of custom code when the wrapped AllTracks object is created. Remember, this method must return a new instance of the type wrapped by Lazy<> before exiting, and you can use any constructor you choose (here, we are still invoking the default constructor of AllTracks):

Code Snippet
  1. class MediaPlayer
  2. {
  3.     // Use a lambda expression to add additional code
  4.     // when the AllTracks object is made.
  5.     private Lazy<AllTracks> allSongs = new Lazy<AllTracks>( () => {
  6.         Console.WriteLine("Creating AllTracks object!");
  7.         return new AllTracks(); });
  8.  
  9.     public AllTracks GetAllTracks()
  10.     {
  11.     // Return all of the songs.
  12.     return allSongs.Value;
  13.     }
  14. }

Sweet! Hopefully you can see the usefulness of the Lazy<> class. If you find this topic useful to your projects, you may also want to look up the System.Lazy<> class in the .NET Framework 4.0 SDK documentation for further examples of how to program for "lazy instantiation".


Posted by: Andrew Troelsen
Posted on: 3/8/2010 at 5:42 AM
Categories: .NET
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

Software as a Service (SaaS)

I have had a very busy couple months ramping up on the new Visual Studio 2010 testing tools and starting a new project.  Now that things have settled down a little bit, cloud computing has hit my radar again.  Several years ago I wrote a white paper on what it would take to deploy my former employers COTS product in a Software as a Service (SaaS) model.  While it wouldn’t be appropriate to share the entire white paper, I reworked the introduction to share my thoughts on SaaS with the community.  What is interesting is that this was written in late 2007 or 2008 and while technology has changed considerably, and the maturity levels may have been renumbered and grown,  I believe all of the concepts are still relevant today. After I spend a little time learning about the new .Net cloud technologies at our disposal, I’ll revisit this post and start discussing how to pull all of this off.

Definition

Software as a Service is a deployment model where an application is hosted as a service over the internet.

Business benefits to the customer

· Reduced cost of maintenance and support. The hardware cost and associated support staff is the vendor’s or a 3rd party’s responsibility.

· Reduced cost of entry by reducing the initial cost of purchasing licenses a pay per use model is generally employed.

Business benefits to the application vender

· Better protection of intellectual property. The customer has much less access to the system. For example there are little or no on-site IT responsibilities so the customer would be much less knowledgeable about things like the data store or application architecture.

· Establishes an ongoing revenue stream. The pay as you go model establishes a more predictable revenue stream.

· Reduced cost of maintenance by controlling the platform that the application is deployed on. For example an application could be deployed and certified only on Windows 2008 and Sql Server 2008. Certifying on one very predictable environment simplifies the QA and support burden.

Risks and Challenges

· Trust. What is the long term viability of the application service provider? How secure is the data? What is the disaster recovery plan? What level of service can I expect?

· Integration. Integrating with on-premise applications is difficult enough, how do we integrate with hosted applications?

· Regulations. Are there regulations around data access and storage that would increase the difficulty of deploying an application in the Software as a Service model?

· Portability. If I want to move the application and data to a new service provider, will my application and data port?

· Support. Who fields help desk type calls

· Management. Maintenance and upgrades are controlled by the service provider.

· Identity Management. Customer will have less control over how users and Identity are managed.

Software as a Service maturity levels

Maturity Level 1 – Each customer has its own customized instance of the application running on the host servers. This is essentially the same as the Application Server Provider (ASP) model of the late 90’s that never really took off. Each customer is executing different code on different machines.

 

 

 

Maturity Level 2 - Each customer has its own configurable instance of the application running on the host servers. Each customer is executing the same code on a different machine.

 

Maturity Level 3 – The vendor hosts all of the customers in a single configurable instance of the application and uses authorization and security policies to ensure that each customer’s data is kept separate from the other customers. This is called multi-tenant; each customer is executing the same code on the same machine.

 

Maturity Level 4 - – The vendor hosts all of the customers in a load balanced farm of identical instances of the application and uses authorization and security policies to ensure that each customer’s data is kept separate from the other customers.

 

A Note on Application Security

When architecting an application to be deployed in an SaaS model it is important to architect the application with security in mind. CIAA is a security acronym standing for Confidentiality, Integrity, Authenticate, and Authorize and as architects we need to consider these things.

Confidentiality - Make sure nobody else can read the messages by encrypting confidential communications.

Integrity - Validate that the message has not been tampered with by using digital signatures.

Authenticate - Make sure the user is who they say they are.

Authorize - Make sure the user is allowed to do what they are trying to do.

A Note on Delivering Large Resources

Distributing large resources in the SaaS deployment model presents a particularly difficult performance challenge when you are trying to deliver large resources. Assume you have to deliver a resource that is 10’s of megabytes in size. The performance a customer can expect is equal to what a customer gets when downloading a similar size file from the internet. Software designers should consider an architecture which supports distributing these large resources to local stores. These local stores would host the large documents at various locations around the world, within an intranet, or ideally on a local network. The hosted service would still own and manage the documents but the local stores would have to communicate with the master store to ensure that the large resources are up to date.

 

 

 


Posted by: Tim Star
Posted on: 3/5/2010 at 4:07 PM
Tags: , ,
Categories: .NET
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

Nexus OSS hosting - fast and easy

An SMTP Test Server

I am working on a new product for a customer, and it will send a number of emails to users.  I also set up sending emails to the development team for runtime diagnostic information for "those situations".

Of course, we need automated integration tests (ITs), aka functional tests, to prove these email features work.  There are a number of OSS SMTP server products to use, and the key thing is to use one that is fast & easy to setup and teardown in a functional test.

This time I chose SubEtha SMTP, a Java library with a simple email test harness named Wiser.  It's fast, easy, and works well in the functional tests.

Not Current

There was one problem though, the latest SubEtha SMTP version in Maven Central repository was really old, and we encountered a couple of problems that were fixed in more recent versions.  We needed the newest version, and since I have been successfully using Maven for over 5 years, and again on this project, this was important to resolve.

Fix It

I could have simply built SubEtha SMTP and deployed it to my customer's local Maven repo, hosted by Nexus (setup and managed by me!).  But that doesn't solve the real problem.  Since SubEtha SMTP was a pretty good product, I wanted to solve the problem permanently and for others.

Create Maven Build

I planned to create one, but found an existing request in SubEtha's issue tracker to deploy a new release to Maven Central and commented in it.  A discussion ensued; the summary is the SubEtha developers didn't care to use Maven or deal with Maven Central repo updates.  However, they were happy to have me do it for them.  So I created a POM for SubEtha SMTP and committed it.  With a simple command, Maven builds and packages the product into a jar, and also creates jars of the source and JavaDoc.  Almost there?

Host It

The next step was to setup something to get the artifacts to Maven Central.  I've done this before on other OSS products I've worked on, and it involved either a manual upload request (no thanks!) or syncing with a self-made repo on a forge, like SourceForge.  This was ok, but took some extra effort on my part and extra time waiting for it to happen.

Enter Nexus

Recently, Sonatype, the creators of Nexus (a Maven repository manager), began offering free Maven repository hosting for OSS products.  They have a page for the Nexus OSS Repository Hosting info.  Anyone can use/view the Nexus OSS repo, browsing the product repos and their artifacts already setup there.  Additionally, if the build artifacts comply with a number of items, the repo owner can request to have the Nexus OSS repo automatically synced with Maven Central.  Hmmm, sounds perfect.

Having setup Nexus for my current and prior customers (I even used and liked its predecessor, Proximity!), I know what a great product it is.  With the need to get SubEtha SMTP to Maven Central repo, this seemed like the best option - using it as the public repo and auto-syncs to Central.

Couldn't Be Easier

Setting it up was very easy - I just read and followed the information on the Nexus OSS Repo Hosting page.  I created the JIRA ticket requesting the Nexus repo on a Saturday, and Monday morning it was created.  That Monday night, I deployed to the new repo, and then requested the auto-sync to Central.  Approximately 5 hours later, the auto-sync was approved and occurred!  It can't get faster and easier than that! 

Done - D. U. N.

As my wonderful grandfather used to say, "Done, D  U  N"; I have very fond memories of him teasing me with that errant spelling when I was wayyyy too young to understand!  :-)

I reported the successful deploy to Maven Central on the SubEtha SMTP issue, closed it as fixed, and received a couple of thank you's :-).

Thank you Sonatype for creating Nexus and offering this service!  It is fantastic.  I'll move other projects' artifacts to there as well.

P.S.

Interestingly, with the many problems on java.net, especially with the (lack of) support for Maven deployed artifacts there, Sonatype is orchestrating a great effort to help java.net projects migrate their Maven repo hosting to Nexus OSS.  For more information on that, read the Sonatype blog on Java.net Maven Repository Rescue Mission on March 5th.


Posted by: Jeff Jensen
Posted on: 3/1/2010 at 11:34 PM
Tags: , ,
Categories: Java
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

What Makes a Good Customer

This blog entry, as well as subsequent future entries, are from an upcoming book...

What makes a good customer? This might strike you as an odd question, after all, isn’t it the vendor’s responsibility to make the relationship work? While a vendor must go the extra mile, the customer also has obligations in making a vendor relationship effective. I think the same qualities apply to a good customer as to a good employee, a good friend, even a good spouse: trust, mutual respect and appreciation, and sharing that shows that each is committed to the success of the partnership.

Good customers:

  • Clearly communicate expectations. Assumptions are a bad thing. Customers who share their expectations openly and early are much happier with their project outcomes.
  • Provide clear direction and feedback to the project team to control scope.
  • Understand that changes to a project that modify the original base requirements, often are necessary to provide the best solution. To account for this, a good solution is a change management plan, defined at the start of the project that outlines a formal process for changes. This process includes criteria used to determine if a change will actually be implemented or deferred to a later date.
  • Take initiative in quickly removing road blocks for those doing the work.
  • Share responsibility for success of delivery.
  • Work to diminish the political boundaries that can emerge between consultants and full-time employees. Along with this, a good consulting team works hard to accelerate the expertise of existing employees so they can successfully maintain what they’re responsible for when the contract ends.
  • Become actively engaged in the process all along the way (and gets key people involved and with some ownership).
  • Do not overreact to minor setbacks.
  • Communicate on a daily basis.

My Takeaway: Good customer-vendor relationships require both parties to participate, communicate and share responsibility for a successful outcome.


Posted by: Tom Salonek
Posted on: 2/26/2010 at 2:34 PM
Tags: , ,
Categories: General | Business
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

Introducing Data Parallelism using the .NET 4.0 TPL

With the release of .NET 4.0, we are provided with a brand new parallel programming library (the Task Parallel Library, or TPL). Using the types of System.Threading.Tasks, you can build fine-grained, scalable parallel code without having to work directly with threads or the thread pool. Furthermore, when you do so, you can make use of strongly typed LINQ queries (via "parallel LINQ", or PLINQ) to divide up your workload.

 

The primary class of the TPL is System.Threading.Tasks.Parallel.  This class supports a number of methods which allow you to iterate over a collection of data (specifically, an object implementing IEnumerable<T>) in a parallel fashion. If you were to look up the Parallel class in the .NET Framework 4.0 SDK documentation, you'll see that this class supports two primary static methods, Parallel.For() and Parallel.ForEach(), each of which defines numerous overloaded versions.

Both of these methods require you to specify an IEnumerable or IEnumerable<T> compatible container that holds the data you need to process in a parallel manner. The container could be a simple array, a non-generic collection (such as ArrayList), a generic collection (such as List<T>) or the results of a LINQ query.

In addition, you will need to make use of the System.Func<T> and System.Action<T> delegates to specify the target method which will be called to process the data. Recall that Func<T> represents a method which can have a given return value and a varied number of arguments. The Action<T> delegate is very similar to Func<T>, in that it allows you to point to a method taking some number of parameters.  However, Action<T> specifies a method which can only return void.

While you could call the Parallel.For() and Parallel.ForEach() methods and pass a strongly typed Func<T> or Action<T> delegate object, you can simplify your programming by making use of a fitting C# anonymous method or lambda expression.

One way to use the TPL is to perform data parallelism. Simply put, this term refers to the task of iterating over an array or collection in a parallel manner using the Parallel.For() or Parallel.ForEach() methods. Assume you need to perform some labor intensive File IO operations.  Specifically, you need to load a large number of *.jpg files into memory, flip them upside-down, and save the modified image data to a new location. Consider the following code snippet, which uses is currently *not* using TPL to process each image file:

private void ProcessFiles()
{
  // Load up all *.jpg files, and make a new folder for the modified data.
  string[] files = Directory.GetFiles
    (@"C:\Users\AndrewTroelsen\Pictures\My Family", "*.jpg",
    SearchOption.AllDirectories);
  string newDir = @"C:\ModifiedPictures";
  Directory.CreateDirectory(newDir);

  //  Process the image data in a blocking manner. 
  foreach (string currentFile in files)
  {
    string filename = Path.GetFileName(currentFile);

    using (Bitmap bitmap = new Bitmap(currentFile))
    {
      bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone);
      bitmap.Save(Path.Combine(newDir, filename));
      this.Text = string.Format("Processing {0} on thread {1}", filename,
        Thread.CurrentThread.ManagedThreadId);
    }
  }
  this.Text = "All done!";
}

If we were to call this method from a Button Click, the UI would hang for some time, as the primary thread is waiting to complete the lengthy processing of image file. We can replace the C# foreach loop with the following code, which will inform the TPL to iterate over the data. 

//  Process the image data in a parallel manner! 
Parallel.ForEach(files, currentFile =>
  {
    string filename = Path.GetFileName(currentFile);

    using (Bitmap bitmap = new Bitmap(currentFile))
    {
      bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone);
      bitmap.Save(Path.Combine(newDir, filename));
      this.Text = string.Format("Processing {0} on thread {1}", filename,
                  Thread.CurrentThread.ManagedThreadId);
    }
  }
);

Now, if you run program, the TPL will indeed distribute the workload to multiple threads from the thread pool, using as many CPUs as possible.  However, you will not see the window's caption display the name of each unique thread!  The reason is that the primary UI thread is still blocked, waiting for all of the other threads to finish up their business.

 

To keep the user interface responsive, you could certainly make use of asynchronous delegates or the members of the System.Threading namespace directly, but the System.Threading.Tasks namespace provides a simpler alternative, via the Task class. Task allows you to easily invoke a method on a secondary thread, and can be used as a simple alternative to working with asynchronous delegates. Here is a Click handler for a button control which will run the parallel code in a non-blocking manner: 

private void btnProcessImages_Click(object sender, EventArgs e)
{
  // Start a new "task" to process the files. 
  Task.Factory.StartNew(() =>
  {
    ProcessFiles();
  });
}

 

The Factory property of Task returns a TaskFactory object.  When you call its StartNew() method, you pass in an Action<T> delegate (here, hidden away with a fitting lambda expression) which points to the method to invoke in an asynchronous manner. With this small update, you will now find that the window's title will show which thread from the thread pool is processing a given file, and better yet, the text area is able to receive input, as the UI thread is no longer blocked.

 

This is just one small example of how the new TPL can simplify the development of multithreaded programs, which automatically leverage (where possible) the CPUs on the target machine.

 

 

 

 

 

 

 

 

 


Posted by: Andrew Troelsen
Posted on: 2/23/2010 at 8:31 AM
Tags:
Categories: .NET
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

WF 4.0 Input Arguments and Output Arguments

I am sure you are aware that the entire WF programming model has changed (for the better, if you ask me) under .NET 4.0.  Why?  Well, the first release of WF was useful, but many things were much more complex than necessary.  Part of this complexity is due to the fact that the previous version of WF was code driven.  While you could incorportate some markup into the mix, it was not seemless, and not the default approach of Visual Studio. Under WF 4.0, by default, your workflows are authored in XAML.  WF 4.0 XAML even has the ability to embed "real code" into the markup, using [ and ] tokens.  Therefore, when you are using the WF designer it is possible to configure activities using calls to external objects, via LINQ queries, or any other type of logic you would normally author in C# / VB.

Another aspect of the first release of WF which was painful was how we had to create custom properties (in code) which would map to host suppled arguments. While not impossible, WF 4.0 cleans this up quite a bit as well. As of WF 4.0, data variables are a first class citizen. You can declare aguments and variables directly on the WF designer, and use them throughout your workflow. The difference?  An "argument" is a variable which allows you to capture input from the host, or return values you want to send the host. A "variable" is just that- a point of data in your workflow you want to make use of internally.

You can define arguments and variables using the identically named buttons on the workflow designer. Just like when you define a variable in code, they will have a name and type, and possibly a default value.  Assume you want the host to pass you two strings, which you will use to build a LINQ query.  You could begin by adding two Argument variables as seen here:

Now, if we have a Sequence activity as the first child of the root, we could make use of two WriteLine activities to print out the host suppled string data, represented by our HostStringOne and HostStringTwo variables.  As well, we will use an Assign activity to set a value for our output parameter, which will be received by the host.  Do be aware that a workflow can pass back any number of output paramters, so the host could get back a whole collection of information when the workflow completes. 

To send arguments to the workflow, we package up name value pairs in a Dictionary<string, object> object.  If we use the WorrflowInvoker.Invoke() method to spin up the workflow, the returned IDictionary<> comparable object will contain each output parameter.  Consider the following Main() method which sends data to the workflow, and prints out the returned output data:

static void Main(string[] args)
{
  Dictionary<string, object> wfArgs = new Dictionary<string, object>()
  {
    {"HostStringOne", "Testing...."},
    {"HostStringTwo", "....1, 2, 3."}
  };

  IDictionary<string, object> retVals =
    WorkflowInvoker.Invoke(new Workflow1(), wfArgs);

  Console.WriteLine(retVals["DataForHost"]);
}

Notice that we pass the data to  the workflow as a second argument to Invoke(). The output is as you would explect, all data displays to the console. This simple example shows one way that WF 4.0 streamlines the way we work with workflow enabled applications.  If you dismissed the WF API before, I'd encourage you to take a peek at WF 4.0.  It is a whole new ball game.

 


Posted by: Andrew Troelsen
Posted on: 2/18/2010 at 10:46 AM
Tags:
Categories: .NET
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

Working with Headers in JAX-WS SOAPHandlers

By Jim White (Intertech Director of Training and Instructor)

Last week I taught Java Web Services to a great group of gentlemen that were a bit more advanced in their Java/Java EE skills than what I usually have in my classroom.  Therefore, I must admit, they threw some great questions at me.

One question about SOAPHandler (thanks for the great question Kevin) sent me scrambling for a good example on the World Wide Web.  Incredibly, I could not find one.  So, this week's post is all about the JAX-WS SOAPHandler and how to use its getHeaders() method to deal with mustUnderstand attributes in a SOAP message.

JAX-WS Handlers

In addition to support for web services development, the JAX-WS framework (the latest Java programming language API for creating SOAP-based web services and web service consumers) also provides a handler framework.  Handlers provide a means to inspect and manipulate incoming or outgoing SOAP messages (on both the client as well as server side).  They act as powerful message interceptors that can perform an array of functions such as message transformation, content filtering, tracking, etc.  In fact, handlers are often used in runtime environments to implement web service and SOAP specifications such as WS-Security, WS-ReliableMessaging, etc.  JAX-WS handlers are similar to EJB interceptors or servlet filters.  Handlers, like interceptors and filters, encourage developers to follow the chain of responsibility pattern.

Two Types of Handlers

JAX-WS provides two types of handlers (with two interfaces): LogicalHandler and SOAPHandler.  LogicalHandlers are message protocol neutral. LogicalHandlers only have access to the message payload of a message.  SOAPHandlers are also known as message or protocol handlers.  SOAPHandlers have access to the entire SOAP message.

SOAPHandlers

The SOAPHandler interface requires that the handler class implements four methods: handleMessage, handleFault, close, and getHeaders.  The handleMessage is typically the method of most interest in a handler.  The handleMessage method gets invoked for normal processing by the framework as a message is either sent or received (inbound and outbound).  The handleFault method gets invoked by the framework when a SOAP fault is thrown during message processing.  The close method is invoked by the framework just before dispatch of the message.  The close method allows any cleanup or resource release at the end of handler processing.

Below is an example of a SOAPHandler (minus the getHeaders method which is covered below) that counts the number of elements in both the header and body of a SOAP message.

//required imports here

public class HeaderHandler implements SOAPHandler<SOAPMessageContext> {

    @Override
    public void close(MessageContext context) {
    }

    @Override
    public boolean handleFault(SOAPMessageContext context) {
        return false;
    }

    @Override
    public boolean handleMessage(SOAPMessageContext messagecontext) {
        Boolean outbound = (Boolean) messagecontext
                .get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
        if (outbound) {
            System.out.println("SOAP message departing...");
        } else {
            System.out.println("SOAP message incoming...");
        }
        try {
            SOAPMessage message = messagecontext.getMessage();
            SOAPHeader header = message.getSOAPHeader();
            if (header != null) {
                Iterator<?> i = header.getChildElements();
                System.out.println("Number of header elements:  "
                        + countElements(i));
            }
            SOAPBody body = message.getSOAPBody();
            if (body != null) {
                Iterator<?> i = body.getChildElements();
                System.out.println("Number of body elements:  "
                        + countElements(i));
            }
        } catch (Exception e) {
            System.out.println(e);
            e.printStackTrace();
        }
        return true;
    }

    private int countElements(Iterator<?> i) {
        int count = 0;
        while (i.hasNext()) {
            count++;
            i.next();
        }
        return count;
    }

}

It is the last method, getHeaders, that is the focus of this blog post.  The getHeaders method retrieves the header blocks that can be processed by the handler. It takes no arguments and returns a set of qualified header names.

The getHeaders() Method

So exactly what does the the SOAPHandler's getHeaders() method do for you?  It is the getHeaders() method that informs the service hosting runtime what SOAP headers the handler is responsible for processing.  It returns the QNames of the outer element of each SOAP header that the handler understands.

MustUnderstand Not Understood!

If you are familiar with SOAP messages, you know that SOAP header elements may come with a mustUnderstand global SOAP attribute.  Valid values for mustUnderstand are true|false (SOAP 1.2) or 1|0 (SOAP 1.1).  This attribute is used to indicate whether or not the web service receiver or intermediary is required to understand the header element before processing the message.  A SOAPHandler can server as an "intermediary" that process the SOAP header before the actual service processes the rest (the body) of the message.

For example, below is a sample SOAP message that contains fake security credentials for use by the server side to authenticate/authorize some service invocation.  Notice the mustUnderstand attribute on both the username and password header elements?

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Header>
      <secty:username soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next" soapenv:mustUnderstand="1" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:secty="urn:com.intertech.secty">Jim</secty:username>
      <secty:password soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next" soapenv:mustUnderstand="1" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:secty="urn:com.intertech.secty">supersecret</secty:password>
   </soapenv:Header>
   <soapenv:Body>
      <tns:getContact xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="http://service.intertech.com/">
         <arg0>4</arg0>
      </tns:getContact>
   </soapenv:Body>
</soapenv:Envelope>

If something does not process the username and password header elements, this message would result in a fault back to the client.  For example, assume that the service did not handle the header elements and the SOAP Handler's getHeaders() method was coded as shown below.

    @Override
    public Set<QName> getHeaders() {
        return null;
    }

Since nothing handles the username and password headers, the resulting SOAP message to the client would include a MustUnderstand fault code as shown here.

<soap:Envelope
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <soap:Fault>
         <faultcode>soap:MustUnderstand</faultcode>
         <faultstring>MustUnderstand headers: [{urn:com.intertech.secty}password, {urn:com.intertech.secty}username] are not understood.</faultstring>
      </soap:Fault>
   </soap:Body>
</soap:Envelope>

Using getHeaders() to Understand the MustUnderstand

However, the getHeaders() method can be coded to tell the runtime environment that the SOAP handler is going to take care of the mustUnderstand header elements by returning a set of QName (qualified name) objects that match the mustUnderstand header elements.  Below is the new getHeaders() method that handles the username and password headers of this example.

@Override
public Set<QName> getHeaders() {
    System.out.println("Inside SOAP handler of get Headers");
    QName securityUsernameHeader = new QName("urn:com.intertech.secty",
            "username");
    QName securityPasswordHeader = new QName("urn:com.intertech.secty",
            "password");
    HashSet<QName> headers = new HashSet<QName>();
    headers.add(securityUsernameHeader);
    headers.add(securityPasswordHeader);
    System.out.println("got Headers:  " + headers);
    return headers;
}

Now, if the same SOAP element with the username and password header elements was sent to a service and through the HeaderHandler above, a fault is not generated.  It is assumed by the runtime that the header elements were consumed by the handler.  Of course, in a real world SOAP handler, in the handleMessage( ) method you would now want to add code to actually handle these headers.

Thanks again to my students for a great week in class and for the great Java web services questions.  Special thanks to Kevin for bringing up this topic and seeking more information.  Hopefully this example will help him and you wrestle with JAX-WS SOAP Handlers.

If you would like to learn more about Java and Java Web Services, come join me in Intertech's Complete Java Web Services training.  We'd love to have you.


Posted by: Jim White
Posted on: 2/15/2010 at 4:47 PM
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

Customized Java ME LWUIT Components

by Jim White (Intertech Director of Training and Instructor)

Several months ago, I wrote an article for DevX that introduced Java ME developers to an exciting new GUI library called LWUIT (lightweight UI toolkit) for creating richer and more portable user interfaces for Java ME applications (see http://www.devx.com/wireless/Article/38461). I still get emails because of that article. Evidence, I think, of LWUIT?s growing popularity in the Java ME community.

Most of the emails I receive want to know how to adopt and extend the framework. In fact, one of LWUIT?s strengths is that, like Java Swing from whose design inspired LWUIT, you can extend many of the LWUIT classes to add your own functionality.

Take for example an email I received from a Java ME in Bangalore, India this week. He wanted to know how to create a text field widget that only accepts characters. LWUIT?s TextField class (com.sun.lwuit.TextField) and TextArea class (com.sun.lwuit.TextArea) from which it descends allows the developer to constrain user entry to numerics, decimals, email addresses, URLs, and even phone numbers (see LWUIT API at https://lwuit.dev.java.net/nonav/javadocs/index.html). However this widget does not innately allow input to be constrained to characters (A-Z, a-z) only!

On solution is to further extend TextField (or TextArea) further. In your new TextField class, override the setText method to accept only characters. Overriding insertChar(String c) would also allow you to check characters entered directly in the widget, but you may to also check characters entered, for example, by qwerty mode.

package com.intertech.lwuit;

import com.sun.lwuit.TextField;

public class MyTextField extends TextField {
   public void setText(String text){
       super.setText(alphaOnly(text));
   }

   private String alphaOnly(String text){
       StringBuffer charOnlyText = new StringBuffer();
       for(int i = 0; i < text.length(); i++){
           char c = text.charAt(i);
           int c_i = c;
           if (( c_i >= 65 && c_i <= 90) || ( c_i >= 97 && c_i <= 122 )) {
               charOnlyText.append(c);
           }
       }
       return charOnlyText.toString();
   }
}

Any good framework helps provide the tools for tackling the most common needs. Few, if any, frameworks provide for your every need. A good framework like LWUIT also provides you an API that can be easily extended to address those needs not directly provided by the framework.

Come learn more about Java and the various API?s and open source frameworks with training classes at www.intertech.com.


Posted by: Jim White
Posted on: 2/11/2010 at 12:37 PM
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

How to Get a Promotion (Tips 11-20)

This is a continuation of a previous post

  1. Take Blame.  Give Praise.  Author Jim Collins shared that great leaders “Look in a mirror when there’s a problem and look out a window when there’s success.”  Give praise.  Congratulate and thank in writing.  When someone’s had success, ask them how they did it.  They can relive their glory for a few minutes.  If a problem happens, own your part.  If a problem happens with someone on your team and you’re dealing with your client or end customer, take responsibility.
  2. Shoot for a career not a job.  Know your business, your industry, and your profession.  When it comes to your firm, know the stock price, leadership changes, new products, and news.  When it comes to your industry and profession, read, understand trends, stay current. 
  3. Act the way you want others to act.  Attitudes are contagious.  People cannot control your emotions – only you can.  If you are upset and not sure if you should say something – don’t.  Rarely will people think you acted unprofessionally if you say little or nothing.  Don’t accept a “gift” of anger.  In line with controlling your emotions, don’t respond in kind when someone is angry.  By not accepting their gift of anger – it remains with them.
  4. When there are problems, think and speak solutions.  If the focus is on me, my hurt feelings, what happened in the past, gossip etc., time ticks away as laundry lists of bad feelings build and emotions boil.  Meanwhile, the solution is still waiting to be discovered.  Engage in direct communication.  Venting to a third party doesn’t change any situation and can disrupt office harmony.  Address concerns, criticisms and wants to the appropriate members (those who have the power to make changes to policy or guidelines) of the company.  Use I statements.  I statements make our thoughts clear to our listeners.   You statements imply blame.  Don’t take it upon yourself to represent the concerns of coworkers.  Each employee is responsible for stating his/her own concerns and suggestions.
  5. Lead up… When you bring your manager a question or a problem, bring along a few possible solutions.  Be ready to tell your manager which solution you think is best and why.  Don’t use the manager’s time to think through the problem if this is something you could do beforehand.  Prepare your manager for bad news early.  This allows your manager time to help you, defend you, or prepare other parties for what is to come.  Once you’ve owned and defined the problem, cut to the quick in finding a solution.
  6. Seek to understand before you seek to be understood.
  7. Adversity reveals not builds character.  It shows others how we are “wired” at our core.  Leadership at your firm and your end customer will reward and remember you behaving with character and being committed to solving the problem.  “I don’t know” is okay, especially when teamed with “I’ll find out.”  This is much safer than bluffing.  It shows you are honest and you are not panicking in the face of a challenge.  If you follow up with an answer quickly, it shows you are responsive.
  8. Understand negotiation.  More successful negotiations occur over lunch, dinner and in the hallway after hours than occur at a conference table with one side pitted against another.  Reaching agreement requires trust.  Trust doesn’t get built without work and understanding.  Invest in the relationship and get to know the person with whom you will be working.
  9. Understand the human condition... 
    • “You never get a second chance to make a first impression” isn’t correct.  Data shows we remember the finish more than the start.  Finish strong.  
    • If you have bad news, give a choice.  Giving a choice, even if it’s between two bad scenarios, makes the receiver of your news feel like they have some control.  Having control in a situation creates less stress. 
    • Extend Wins, Cut Losses.  In a study, participants were given a choice.  They could win $5 twice or win $10 once.  Most choice to win $5 twice.  In this same study, participants were given a choice to lose $5 twice or lose $10 once.  Most chose to lose $10 once.  When dealing with others, if good news arises, share it as it comes.  If you have bad news, it’s better to unveil it all at once.
  10. Focus your mind on what you want.  The multi-billion dollar success industry is best summed up by one of the early pioneers, Earle Nightingale.  He said, “We become what we think about.”

Posted by: Tom Salonek
Posted on: 2/9/2010 at 6:20 PM
Tags: , ,
Categories: Career Advice | General
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed