In previous post, we saw how easy it is to use J2EE as a rich backend. Let’s continue with our example and show how to fetch and send some data from our J2EE backend to a Silverlight rich client application. Let’s continue our work using a simple Blog domain model.

Domain Model

To create our simple domain model, let’s create the domain classes in java and let JPA create the database for us. For .NET developers familiar with NHibernate and NHibernate Mapping Attributes project, when comparing this to .NET coding style, there should be nothing new here. Here’s a piece of code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package ir.silverbox.domain;

import javax.persistence.*;
import java.util.List;

@Table(name = "sl_Post")
@Entity
public class Post {

private int postId;
private String title;
private Blog blog;
private List<Comment> comments;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "PostId", nullable = false)
public int getPostId() {
return postId;
}

public void setPostId(int postId) {
this.postId = postId;
}

@ManyToOne
public Blog getBlog() {
return blog;
}

public void setBlog(Blog blog) {
this.blog = blog;
}

@Column(name = "Title", nullable = false)
public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

@OneToMany(mappedBy = "post")
public List<Comment> getComments() {
return comments;
}

public void setComments(List<Comment> comments) {
this.comments = comments;
}
}

package ir.silverbox.domain;

import javax.persistence.*;

@Table(name = "sl_Comment")
@Entity
public class Comment {

private int commentId;
private Post post;
private String text;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "CommentId", nullable = false)
public int getCommentId() {
return commentId;
}

public void setCommentId(int commentId) {
this.commentId = commentId;
}

@ManyToOne()
public Post getPost() {
return post;
}

public void setPost(Post post) {
this.post = post;
}

@Column(name = "CommentText", nullable = false)
public String getText() {
return text;
}

public void setText(String text) {
this.text = text;
}
}

Let’s create a service to return a list of all available Posts and display them on our Silverlight client. Continuing from previous post, you’ve already learned how to create services (or SessionBeans as called in EJB context) but when you actually have an entity model and want to expose it through service, you’d better think twice. There are a lot of things that can go wrong if you do so:

  • Your change in domain model will ripple to your clients because of changes in service contract and will probably break all your clients.
  • Your domain model might contain sensitive information which is best kept on your service tier.
  • Other technical stuff such as your entities beiing lazy and having problems with serialization process.

So before continuing, let’s create some DTO objects which will be sent across the service boundary. For this sample, a POJO class resembling your existing Post entity would suffice. To map between Entities and DTOs, you can roll your own mapper classes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package ir.silverbox.common;

import ir.silverbox.domain.Post;
import javax.ejb.Remote;
import java.util.List;

@Remote
public interface BlogService {
List<PostDto> getAllPosts();
}


package ir.silverbox.services;

import ir.silverbox.common.BlogService;
import ir.silverbox.domain.Post;
import javax.ejb.*;
import javax.jws.*;
import javax.persistence.*;
import java.util.*;

@Stateless(name = "BlogService")
@Remote(BlogService.class)
@WebService
public class BlogServiceImpl implements BlogService {

@PersistenceContext
protected EntityManager em;

public List<PostDto> getAllPosts() {
Query query = em.createQuery("FROM Post");
List<Post> result = query.setMaxResults(10)
.getResultList();

return new PostMapper().MapMany(result);
}
}

Did you notice the EntityManager? It is injected automatically by EJB container and the good thing is you can inject other services, even your other EJB session beans too. EntityManager provides functionalities similar to ISession in N/Hiberante such as CreateQuery, Find, Attach/Detach, Flush, etc.

Now let’s create a new Silverlight application and add a new Service Reference to your project which points to our new service at:

http://localhost:9090/Silverbox/BlogService?WSDL

Service Reference

Use IP / Port of your JBoss server, port is usually 8080. Mind the small / caps characters.

If you open the proxy sources which is automatically generated, you’ll notice our DTO objects are all here in our Silverlight application now! There’s a slight modification though: All the classes and properties are named according to java naming conventions so our PostDto class is now named “postDto” on the Silverlight client. This is happened to all the properties of the proxy classes too so if you’re binding generated classes directly to your UI keep in mind that Xaml binding are case sensitive. What is good is that INotifyPropertyChange is already implemented. The rest is just regular Silverlight application calling a remote service:

1
2
3
4
5
6
7
8
9
10
11
12
<Grid x:Name="LayoutRoot">
<ListBox x:Name="RecentPosts">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=postDate}" />
<TextBlock Text="{Binding Path=title}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>

and to call the service:

1
2
3
4
5
6
7
8
9
10
11
12
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
var service = new BlogServiceImplClient();
service.GetAllPostsCompleted += (snd, arg) =>
{
if(arg.Error == null)
{
RecentPosts.ItemsSource = arg.Result;
}
};
service.GetAllPostsAsync();
}

You should have a rich application that is bound to your database using your service layer on J2EE. Pretty easy so far, don’t you think?

Running Application

Next post in this serie will show you how to handle business validation using SoapFaults, how to serialize Java exceptions into Silverlight client and how to actually deploy the whole application. Get the sources of this part from here.