The code is exactly as a normal Java POJO, but using the Java EE annotations to enhance the behaviour. @ApplicationPath("/resources") and @Path("persons") will expose the REST service at the url yourdomain/resources/persons (yourdomain will be the host where the application is running). @Consumes(MediaType.APPLICATION_JSON) and @Produces(MediaType.APPLICATION_JSON) accept and format REST request and response as JSON.

For the REST operations:

Annotation / HTTP Method

Java Method

URL

Behaviour

@GET / GET

listPersons

http://yourdomain/resources/persons

Returns a paginated list of 10 persons.

@GET / GET

getPerson

http://yourdomain/resources/persons/{id}

Returns a Person entity by it’s id.

@POST / POST

savePerson

http://yourdomain/resources/persons

Creates or Updates a Person.

@DELETE / DELETE

deletePerson

http://yourdomain/resources/persons/{id}

Deletes a Person entity by it’s id.

The url invoked for each operations is very similar. The magic to distinguish which operation needs to be called is defined in the HTTP method itself when the request is submitted. Check HTTP Method definitions.

For getPerson and deletePerson note that we added the annotation @Path("{id}") which defines an optional path to call the service. Since we need to know which object we want to get or delete, we need to indicate the id somehow. This is done in the service url to be called, so if we want to delete the Person with id 1, we would call http://yourdomain/resources/persons/1 with the HTTP method DELETE.

That’s it for the backend stuff. Only 30 lines of code added to the old REST service. I have also added a new property to the Person object, to hold a link to image with the purpose of displaying an avatar of the person.

UI – Angular JS

For the UI part, I’ve decided to split it into 3 sections: the grid, the form and the feedback messages sections, each with its own Angular controller. The grid is mostly the same from Part 1, but it did require some tweaks for the new stuff:

Grid HTML

Grid HTML

XHTML

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

<!-- Specify a Angular controller script that binds Javascript variables to the grid.-->

// Broadcast an event when an element in the grid is deleted. No real deletion is perfomed at this point.

$scope.deleteRow=function(row){

$rootScope.$broadcast('deletePerson',row.entity.id);

};

// Watch the sortInfo variable. If changes are detected than we need to refresh the grid.

// This also works for the first page access, since we assign the initial sorting in the initialize section.

$scope.$watch('sortInfo.fields[0]',function(){

$scope.refreshGrid();

},true);

// Do something when the grid is sorted.

// The grid throws the ngGridEventSorted that gets picked up here and assigns the sortInfo to the scope.

// This will allow to watch the sortInfo in the scope for changed and refresh the grid.

$scope.$on('ngGridEventSorted',function(event,sortInfo){

$scope.sortInfo=sortInfo;

});

// Picks the event broadcasted when a person is saved or deleted to refresh the grid elements with the most

// updated information.

$scope.$on('refreshGrid',function(){

$scope.refreshGrid();

});

// Picks the event broadcasted when the form is cleared to also clear the grid selection.

$scope.$on('clear',function(){

$scope.gridOptions.selectAll(false);

});

});

A few more attributes are required to configure the behaviour of the grid. The important bits are the data: 'persons.list' which binds the grid data to Angular model value $scope.persons, the columnDefs which allow us to model the grid as we see fit. Since I wanted to add an option to delete each row, I needed to add a new cell which call the function deleteRow when you click in cross icon. The afterSelectionChanges function is required to update the form data with the person selected in the grid. You can check other grid options here.

The rest of the code is self-explanatory and there is also a few comments in there. A special note about $rootScope.$broadcast: this is used to dispatch an event to all the other controllers. This is a way to communicate between controllers, since the grid, form and feedback messages have separate controllers. If everything was in only one controller, this was not required and a simple function call would be enough. Another possible solution if we want to keep the multiple controllers, would be to use Angular services. The used approach seems much cleaner since it separates the application concerns and does not require you to implement additional Angular services, but it might be a little harder to debug if needed.

Form HTML

Form HTML

XHTML

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

<div class="form"ng-controller="personsFormController">

<!-- Verify person, if there is no id present, that we are Adding a Person -->

<div ng-if="person.id == null">

<h3>Add Person</h3>

</div>

<!-- Otherwise it's an Edit -->

<div ng-if="person.id != null">

<h3>Edit Person</h3>

</div>

<div>

<!-- Specify the function to be called on submit and disable HTML5 validation, since we're using Angular validation-->

<form name="personForm"ng-submit="updatePerson()"novalidate>

<!-- Display an error if the input is invalid and is dirty (only when someone changes the value) -->

A lot of codeis for validation purposes, but lets look into this a bit more in detail: each input element binds its value to person.something. This allows to model the data between the HTML and the Javascript controller, so we can write $scope.person.name in our controller to get the value filled in the form input with name, name. To access the data inside the HTML form we use the form name personForm plus the name of the input field.

HTML5 have its own set of validations in the input fields, but we want to use the Angular ones. In that case, we need to disable form validations by using novalidate at the form element. Now, to use Angular validations, we can use a few Angular directives in the input elements. For this very basic form, we only use required, ng-minlength and ng-maxlength, but you can use others. Just look into the documentation.

Angular assigns CSS classes based on the input validation state. To have an idea, these are the possible values:

State

CSS

On

valid

ng-valid

When the field is valid.

invalid

ng-invalid

When the field is invalid.

pristine

ng-pristine

When the field was never touched before.

dirty

ng-dirty

When the field is changed.

These CSS classes are empty. You need to create them and assign them styles in an included CSS sheet for the application. Instead, we’re going to use styles from Bootstrap which are very nice. For them to work, a few additional classes need to be applied to the elements. The div element enclosing the input needs the CSS class form-group and the input element needs the CSS class form-control.

To display an invalid input field we add ng-class="{'has-error' : personForm.name.$invalid && personForm.name.$dirty}" to the containing input div. This code evaluates if the name in the personForm is invalid and if it’s dirty. It the condition verifies, then the input is displayed as invalid.

Finally, for the form validation messages we need to verify the $error directive for each of the inputs and types of validations being performed. Just add ng-show="personForm.name.$error.minlength" to an HTML display element with a message to warn the user that the name input field is too short.

Form Angular Controller

Form Angular Controller

JavaScript

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

// Create a controller with name personsFormController to bind to the form section.

// Clears the form. Either by clicking the 'Clear' button in the form, or when a successfull save is performed.

$scope.clearForm=function(){

$scope.person=null;

// For some reason, I was unable to clear field values with type 'url' if the value is invalid.

// This is a workaroud. Needs proper investigation.

document.getElementById('imageUrl').value=null;

// Resets the form validation state.

$scope.personForm.$setPristine();

// Broadcast the event to also clear the grid selection.

$rootScope.$broadcast('clear');

};

// Calls the rest method to save a person.

$scope.updatePerson=function(){

personService.save($scope.person).$promise.then(

function(){

// Broadcast the event to refresh the grid.

$rootScope.$broadcast('refreshGrid');

// Broadcast the event to display a save message.

$rootScope.$broadcast('personSaved');

$scope.clearForm();

},

function(){

// Broadcast the event for a server error.

$rootScope.$broadcast('error');

});

};

// Picks up the event broadcasted when the person is selected from the grid and perform the person load by calling

// the appropiate rest service.

$scope.$on('personSelected',function(event,id){

$scope.person=personService.get({id:id});

});

// Picks us the event broadcasted when the person is deleted from the grid and perform the actual person delete by

// calling the appropiate rest service.

$scope.$on('deletePerson',function(event,id){

personService.delete({id:id}).$promise.then(

function(){

// Broadcast the event to refresh the grid.

$rootScope.$broadcast('refreshGrid');

// Broadcast the event to display a delete message.

$rootScope.$broadcast('personDeleted');

$scope.clearForm();

},

function(){

// Broadcast the event for a server error.

$rootScope.$broadcast('error');

});

});

});

For the form controller, we need the two functions that perform the operations associated with the button Clear and the button Save which are self-explanatory. A quick note: for some reason, Angular does not clear input fields which are in invalid state. I did found a few people complaining about the same problem, but I need to investigate this further. Maybe it’s something I’m doing wrong.

REST services are called using save and delete from the $resource object which already implement the correspondent HTTP methods. Check the documentation. You can get a $resource with the following factory:

REST Service

JavaScript

1

2

3

4

// Service that provides persons operations

app.factory('personService',function($resource){

return$resource('resources/persons/:id');

});

The rest of the controller code, are functions to pickup the events created by the grid to load the person data in the form and delete the person. This controller also create a few events. If we add or remove persons, the grid needs to be updated so an event is generated requesting the grid to be updated.

Resources

Since I may modify the code in the future, you can download the original source of this post from the release 3.0. In alternative, clone the repo and checkout the tag from release 3.0 with the following command: git checkout 3.0.

Final Thoughts

The form validation kicks in right after you start typing. Angular 1.3 will have an on blur property to validate only after loosing focus, but I’m still using Angular 1.2.x.

I have to confess that I found the validation code a bit too verbose. I don’t know if there is a way to simplify it, but you shouldn’t need to add each message validation to each input.

A few things are still lacking here, like parameters sanitisation or server side validation. I’ll cover those in a next blog post.

This was a very long post, actually the longest I’ve wrote on my blog. If you reached this far, thank you so much for your time reading this post. I hope you enjoyed it! Let me know if you have any comments.

I require an software like tally and I have been develop customer communication form.
In that application Admin want to send remainder message to user (sms) like way2sms.
Once admin collect user number from database and send automatic message through mobile in online application.
Let me know any free URL to update this concept kindly mention that code details (.Net programming language).

In fact, the datasource used in the application is the default one from the application server. This uses a new features of Java EE 7 called Default Datasources. You can see additional information here and here.

Thank you! For Tomcat it going to be slightly different, because it doesn’t support Java EE. Have you ever consider moving to TomEE? It’s Tomcat plus Java Enterprise Edition. I can help you set up things there.

Thanks Roberto Cortez,
This code and your earlier code part 1 helps me lot to understand angularjs very well. The back end part I converted to Spring Rest Controller and connected to my won database through hibernate and it is working fine.Thanks a lot posting such blogs on internet and helping others to understand the new technology like angaularjs.

Thanks for such a useful and relevant post! I was hoping to see the running example (to help me debug some errors I am getting in the Angular code). When I click your link to http://javaee7-angular.radcortez.cloudbees.net, I get a server error. Is this service discontinued or has the Url changed? Is there anywhere else I can see your fine code in action?

…further…I especially am trying to identify what versions of the .js and .css libraries you are using in the of the index.html? The bower-install does not work on my windows, and I do not know anything about npm, bower, or grunt to debug why that is failing. I really just need to figure out these libraries.

If you are using the latest version of the sample, which you should be, you don’t need to worry about Bower, NPM or Grunt. They are just used to update stuff if needed, but all the files should be in the repo for the sample to work.

Thank you for the feedback. Unfortunately Cloudbees.net stopped offering the hosting so the url doesn’t work anymore. I’ll update the post. In the meanwhile, you can try the sample here:https://codenvy.com/f?id=3qe4qr7mb8i86lpe

Seems that you are not able to reach the Maven repo from your machine? Can you try to access the address http://repo.maven.apache.org/maven2/ with a web browser? If you can’t, there a connectivity problem somewhere. Might be a firewall issue. You need to be able to access the repo to download the required libraries.

this is nani from india . Thank you for excellent intro to angular for java developer. can you help me . plz send me sample ERP(min three module, like profile, tranction,batch) project java,angularjs,mysql, using eclipse IDE ,tomcat server .

It’s uses HTTP Rest. Java exposes the services as REST and JS is able to call them through HTTP, by doing a regular call. You can try opening up in your browser direct links from the HTTP Rest so you can see their response.