Time for action - writing the APIs

By now, you should have prepared the bookshelf-service project structure. Let's write the BookshelfService and Authentication interfaces. Those will be in the package com.packtpub.felix.bookshelf.service.api.

The Authentication interface

The authentication interface here is a very simple one. It is based on a username and password and creates a session when the authentication information is accepted.

public interface Authentication
{
String login(String username, char[] password)
throws InvalidCredentialsException;
void logout(String sessionId);
boolean sessionIsValid(String sessionId);
}

Again, here, the exceptions (for example, InvalidCredentialsException) are not listed; they are left to you to write on your own.

Typically, this interface would be defined in another bundle to allow for flexibility in the selection of an Authentication and Authorization implementation. We won't worry about this here and will just include it in this bundle.

Note

The choice of using char[] for the password, instead of String, is due to the increased security relating to the potentially longer lifespan of a String at garbage collection.

The BookshelfService interface

As said, the BookshelfService interface extends Authentication to add the authentication functionality to its bookshelf management methods:

public interface BookshelfService extends Authentication
{
Set<String> getGroups(String sessionId);

Most of the methods in this interface look a lot like those in the inventory interface. However, they ask for a valid session ID and hide some of the complexity of the third tier.

void addBook(
String session, String isbn, String title,
String author, String category, int rating)
throws BookAlreadyExistsException, InvalidBookException;

We chose to hide the MutableBook, for example, and spread its properties as separate method parameters. Here, this is a choice we have to abstract away from the book factory method.

Depending on the complexity of the bean at hand, you may choose to use the MutableBook and Book objects instead. It would be interesting, later, if you tried to expose it and implement a locking mechanism when a MutableBook is served, thus preventing edits to the entry until it is released.

The modify book operations are restricted to category and rating attribute updates.

void modifyBookCategory(
String session, String isbn, String category)
throws BookNotFoundException, InvalidBookException;
void modifyBookRating(String session, String isbn, int rating)
throws BookNotFoundException, InvalidBookException;
void removeBook(String session, String isbn)
throws BookNotFoundException;
Book getBook(String session, String isbn)
throws BookNotFoundException;

You may have noticed a difference between the way the inventory API and the bookshelf API function. For example, the inventory API would expect you to get a book for modification, then set its category, then save it; while the bookshelf service API makes this operation available as a single method (modifyBookCategory).

This introduced difference is not necessary; the same update mechanism could have been replicated at the business layer. It is mainly to show that, even though one may be naturally inclined to replicate an interface when exposing some of its functionality, this replication is not a rule. Thought must always be given to the way the client may use this information. In our case, the methods exposed by the inventory interface are made flexible for a middle tier using them. Those in the middle tier are made simple for easy client integration.

Search functionality is provided by category, author, title, and given rating.

Set<String> searchBooksByCategory(
String session, String categoryLike);
Set<String> searchBooksByAuthor(
String session, String authorLike);
Set<String> searchBooksByTitle(
String session, String titleLike);
Set<String> searchBooksByRating(
String session, int ratingLower, int ratingUpper);
}

This concludes the BookshelfService interface definition. Next, we move to its implementation.

Have a go hero tailor the bundle to your liking

Did you feel that the BookshelfService interface is not exactly the way you would have implemented it? Or maybe you want to engage your own creativity while going through this case study?

Before moving onto the implementation of the service, you may want to enrich the interface and extend the scope of work. The following are a few ideas:

  • Move the Authentication interface to a separate bundle and implement a proper authentication bundle. You can also find an existing authentication implementation for OSGi and redesign that part of the bookshelf service to use it.
  • Enrich the BookshelfService interface by exposing more search functionality or adding methods such as:
    • startedBook(String session, String isbn): void, to tell the service that the user has just started reading this book
    • finishedBook(String isbn, int rating): void, to mark this book as finished and give it a rating and then include some additional search functions to retrieve books based on those added book attributes
    • getNotStartedBooks(): List<String>, to search for books not marked as started
    • getUnfinishedBooks(): List<String>, to search for books not marked as finished, and so on

Implementing the service

Alright, now we'll implement the service and its activator. The following diagram puts it all in perspective.

Implementing the service

The bookshelf-service bundle holds the service classes and it depends on the bookshelf-inventory-api bundle. The bookshelf-inventory-impl-mock bundle provides the bookshelf-inventory-api functionality (implementation).

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.142.173.238