It's easy as pie getting lost in the bundle jungle!
A few weeks ago I introduced in DRY iBatis DAOs build an UserDetailsService an iBatis based UserService
. To reduce the required number of seven bundles and additional infrastructural requirements like a database we want to use a simple stupid stub implementation.
In the first step, we extract bundle No. eight userservice.api
and implement bundle No. nine the userservice.stub
. Ups we did it again - even more bundles in the jungle. Out of the now nine bundles we choose the following four to escape the bundle jungle during the time of development.
userservice.model
- yeah right, aUser
;-)userservice.api
- the new bundle in the jungle, theUserService
API
userservice.stub
- aHashMap
basedUserService
stub implementationuserservice.security
- a thin adapter implementation publishing the service asUserDetailsService
inside the OSGi container
We removed all database/iBatis dependencies from the development workspace. With the userservice.api
-bundle we opened the door for other implementations: e.g. LDAP, ADS, ...
The API
could look like this:
public interface UserService {
/**
* Register a new {@link User}.
* @param newUser the new user's data.
*/
void registerUser(User newUser);
/**
* Load registered {@link User} by a given id.
* @param username of the {@link User} to load.
* @return the {@link User} identified by the given id.
*/
User loadUserByUsername(String username);
...
Let's write some Groovy test cases.
public class UserServiceStubGroovyTests {
UserService userService = new UserServiceStub()
@Test
public void testGetEmptyList() {
assertTrue(userService.getList().isEmpty())
}
@Test
public void testLoadUserByUsername() {
userService.registerUser(new UserImpl("J.Unit", "junit@invalid.com"))
assertNotNull(userService.loadUserByUsername("J.Unit"))
}
@Test
public void testRemoval() {
userService.registerUser(new UserImpl("J.Unit", "junit@invalid.com"))
userService.remove(42)
assertTrue(userService.getList().isEmpty())
}
}
Now go for the green bar! With a HashMap
based stub implementation:
public class UserServiceStub implements UserService {
private static final AtomicInteger COUNTER = new AtomicInteger(41);
private final Map<Integer, User> users = new ConcurrentHashMap<Integer, User>();
@Override
public void registerUser(User newUser) {
users.put(COUNTER.getAndIncrement(), newUser);
}
@Override
public User loadUserByUsername(String username) {
for (User user : users.values()) {
if (user.getUsername().equals(username)) {
return user;
}
}
throw new IllegalArgumentException();
}
@Override
public void remove(Integer id) {
users.remove(id);
}
...
Wasn't it easy as pie to escape the bundle jungle?
Photo by Filippo Cesarini from Burst