July 29, 2009

Effective Unit Testing EJB 3.0 with OpenEJB

In my latest project we used EJB 3.0 and Maven2. And as any good programmer I wanted to have good code quality, which means good unit test test coverage, but my expectation on how to achieve this in an efficient manner was quite low, since mine previous experience with EJB 2.1 did not include any good testing experience. Even if coding EJB 3.0 has been greatly simplified, the fact still remains that the enterprise bean has still to be deployed before it can be tested. Of course can one program such that the logic is in a POJO rather directly in the bean itself, but to really be sure it is working the enterprise bean has to be deployed in a container, to be testable. So I started looking at different Maven plugin such as, jboss-maven-plugin and cargo-maven2-plugin, but then came across OpenEJB, which is really the salvation if you are developing EJB 3.0 and want good testing possibility. OpenEJB enable unit testing of enterprise beans as any POJO class! Lets look at some examples.
public class UserServiceSLSBTest {
private static final String EXPECTED_USERNAME_1 = "fornamn.1.efternamn@domain.com";
private static final String EXPECTED_USERNAME_2 = "fornamn.2.efternamn@domain.com";
private static final String EXPECTED_USERNAME_3 = "fornamn.3.efternamn@domain.com";
private Context ctx;

@BeforeClass
public static void oneTimeSetUp() {
}

@AfterClass
public static void oneTimeTearDown() {
}

@Before
public void setUp() throws Exception {
Properties props = new Properties();
props.setProperty(Context.INITIAL_CONTEXT_FACTORY,
"org.apache.openejb.client.LocalInitialContextFactory");

props.put("blogUnmanaged", "new://Resource?type=DataSource");
props.put("blogUnmanaged.JtaManaged", "false");
props.put("blogUnmanaged.JdbcDriver", "com.mysql.jdbc.Driver");
props.put("blogUnmanaged.JdbcUrl", "jdbc:mysql://localhost:3306/blog");
props.put("blogUnmanaged.username", "root");
props.put("blogUnmanaged.password", "");
// TODO fix properties hibernate.hbm2ddl.auto=create-drop

ctx = new InitialContext(props);
}

@After
public void tearDown() {
}

private UserServiceLocal createUserService() throws Exception {
Object obj = ctx.lookup(UserServiceSLSB.class.getSimpleName() + "Local");

assertNotNull(obj);
assertTrue(obj instanceof UserServiceLocal);
return (UserServiceLocal) obj;
}

@Test
public void testCreateUser() throws Exception {
UserServiceLocal userService = createUserService();

User user = new User();
user.setUsername(EXPECTED_USERNAME_1);
user.setPassword(EXPECTED_USERNAME_1);
user.setRoles(Roles.ADMIN);

userService.storeUser(user);
}
}


And the Stateless Session Bean

@Stateless
public class UserServiceSLSB implements UserServiceLocal {
private static final Logger log = LoggerFactory.getLogger(UserServiceSLSB.class);
@PersistenceContext(name = "blog-ejb", unitName = "blog-ejb")
protected EntityManager em;
@Resource
private SessionContext context;

@Override
public User findUserByUsername(String username) {
log.info("findUserByUsername username='" + username + "'...");
Query q = em.createQuery("SELECT u from User as u where u.username=:username");
q.setParameter("username", username);
List list = q.getResultList();
return (list.size() > 0) ? (User) list.get(0) : null;
}

private void checkExistingUser(User user) throws DuplicateException {
User existingUser = findUserByUsername(user.getUsername());
if (existingUser != null)
throw new DuplicateException("Duplicate " + user);
}

@Override
public void storeUser(User user) throws CredentialException, DuplicateException {
log.info("storeUser " + user + "...");
checkExistingUser(user);
if (user.getUserId() == null)
em.persist(user);
else
em.merge(user);
}
}


And the SLSB local interface.

@Local
public interface UserServiceLocal {

public User findUserByUsername(String username);

public void storeUser(User user) throws CredentialException, DuplicateException;
}


And in the pom.xml simply add the dependency to OpenEJB and you are ready to go.

<dependency>
<groupId>org.apache.openejb</groupId>
<artifactId>openejb-core</artifactId>
<version>3.1.1</version>
<scope>test</scope>
</dependency>

Playing Commercial DVD with Ubuntu Jaunty Jackalope 9.04

I previously wrote a blog about how to play commercial DVD with Ubuntu Hardy Heron 8.10 Intrepid Ibex, but here comes an update how it is done with the latest Ubuntu.

sudo /usr/share/doc/libdvdread4/install-css.sh

July 22, 2009

Why Previous Java Web Framework Have Failed and Why Apache Wicket Will Succeed.

There exists numerous Java web framework (e.g. Struts, JSF, Spring MVC, etc.) and most of them are build upon the Model-View-Controller pattern, but though they have been used in numerous successful project, the Java community still produces new Java web framework. Why is that? According to me the previous Java web framework have several flaws:
  • The JSP technique is messy and clutters down the view page, maybe not for simple pages, but definitely for more complex pages.
  • The round trip when developing JSP pages is long since JSP pages can not be viewed, without first compiling them and running them in a web container. This severely slows down the project . This is especially true when one is fixing layout issues.
  • Web and JSP developer have different code base. This also slows down the project productivity, since when the web team ships new code or fixes, the JSP developer must copy past that into different JSP code.
  • Verbose XML configuration, is something the entire Java community is trying to get away from via Annotation and better default values. For example look at the EJB or Spring developing.
  • It is hard and verbose to unit test and even harder to maintain.
Though these many flaws there has not been any good alternative around to develop Java web solution, but now I would say the missing link is found – Apache Wicket.

The Apache Wicket architecture differs in two major way.
  • It does not use JSP technology for coding Views, instead it uses simple HTML and extend it with attributes.
  • You create components (TextField, CheckBox, etc.) in the Controller and add behavioral via Listener classes, such as in Swing.
These two major differences make a huge different:
  • Web and View developer use the same code base.
  • No need to compile and run the View in a container, simply open the View in a web browser and watch differences.
  • Easy to write unit test code.
Before going through an example, lets first take a brief overview over the main Wicket classes. Component are simple Java classes with supporting HTML markup.
Each Components holds a Model that is a simple Java class with data.

What is here imported is that the default Model are stateful and most example for Wicket uses the default model. This is unfortunate because that is not best practice, because stateful objects consume memory and make the application less scalable. The two most imported classes two use to make the application stateless is

IModel usersModel = new LoadableDetachableModel() {
protected Object load() {
return WicketApplication.get().getUserService().getUsers();
}
};

and

new BookmarkablePageLink(“newUser”, UserEditPage.class);

and if you need to pass data use Link with as little data as possible.

Link view = new Link("editUser", itemList.getModel()) {
public void onClick() {
setResponsePage(new UserEditPage(user.getUserId()));
}
};

Now look how easy and clean the unit test is:

public class UserEditPageTest extends TestCase {
protected static final Logger log = Logger.getLogger(UserEditPageTest.class);
private WicketTester tester;

public void setUp() {
tester = new WicketTester(new WicketApplication());
}

private void setUpNewUserEditPage() {
tester.startPage(UserEditPage.class);
tester.assertRenderedPage(UserEditPage.class);
}

public void testLayout() {
setUpNewUserEditPage();

tester.assertComponent(UserEditPage.FEEDBACK_PANEL, FeedbackPanel.class);
tester.assertComponent(UserEditPage.USER_FORM, Form.class);
}

public void testNewUser() {
setUpNewUserEditPage();

FormTester form = tester.newFormTester(UserEditPage.USER_FORM);
form.setValue(UserEditPage.USERNAME, "kalle.stropp@fake.com");
form.setValue(UserEditPage.PASSWORD, "validpassword");
form.select(UserEditPage.ROLES, 0);
form.submit(FormBuilder.BUTTON_SAVE);

tester.assertRenderedPage(UserListPage.class);
tester.assertNoErrorMessage();
}
}


And here follows the rest of the code:


public class UserEditPage extends TemplatePage implements ButtonListener, IChoiceRenderer {
private static final long serialVersionUID = 1L;
protected static final String FEEDBACK_PANEL = "feedbackPanel";
protected static final String USER_FORM = "userForm";
protected static final String USER_ID = "userId";
protected static final String USERNAME = "username";
protected static final String PASSWORD = "password";
protected static final String ROLES = "roles";
protected static final Logger log = Logger.getLogger(UserEditPage.class);

public UserEditPage() {
setModel(new CompoundPropertyModel(new LoadableDetachableModel() {
private static final long serialVersionUID = 1L;

protected Object load() {
return new User();
}
}));
init(false);
}

public UserEditPage(final long userId) {
setModel(new CompoundPropertyModel(new LoadableDetachableModel() {
private static final long serialVersionUID = 1L;

protected Object load() {
User user = WicketApplication.get().getUserService().loadUser(userId);
user.setPassword(null); // hide current password
return user;
}
}));
init(true);
}

protected String getPageTitle() {
return "userEditPage.title";
}

public void init(boolean readOnly) {
add(new FeedbackPanel(FEEDBACK_PANEL));
add(createForm(readOnly));
}

public Form createForm(boolean readOnly) {
FormBuilder builder = new FormBuilder(USER_FORM, getModel());
builder.addLabel(USER_ID);
builder.addTextField(USERNAME, true, 30, readOnly);
builder.addPasswordTextField(PASSWORD);
User user = (User) builder.getModelObject();
builder.addDropDownChoice(ROLES, Arrays.asList(user.getRoles().getValues()), this);
builder.addSubmitButton(this);
return builder.create();
}

@Override
public void onSubmit(Object modelObject) {
log.info("onSubmit " + modelObject);
WicketApplication.get().getUserService().storeUser((User) modelObject);
setResponsePage(UserListPage.class);
}

@Override
public Object getDisplayValue(Object object) {
return ((Roles) object).getRole();
}

@Override
public String getIdValue(Object object, int index) {
return ((Roles) object).getRole();
}
}


And the HTML


<html >
<head > </head >
<body >

<wicket:extend >

<div wicket:id="feedbackPanel" >Feedback Panel </div >

<form wicket:id="userForm" >
<fieldset style="width:250px;" >
<legend > <wicket:message key="userEditPage.userForm" >User Form </wicket:message > </legend >
<table >
<tr >
<td align="right" > <wicket:message key="userEditPage.userId" >UserId </wicket:message >: </td >
<td > <span wicket:id="userId" id="userId" >1 </span > </td >
</tr >
<tr >
<td align="right" > <wicket:message key="userEditPage.username" > <u >U </u >sername </wicket:message >: </td >
<td > <input wicket:id="username" type="text" name="username" accesskey="u" / > </td >
</tr >
<tr >
<td align="right" > <wicket:message key="userEditPage.newPassword" >New <u >p </u >assword </wicket:message >: </td >
<td > <input wicket:id="password" type="password" name="password" accesskey="p" / > </td >
</tr >
<tr >
<td align="right" > <wicket:message key="userEditPage.roles" > <u >R </u >oles </wicket:message >: </td >
<td > <select wicket:id="roles" > </select > </td >
</tr >
<tr >
<td colspan="2" align="right" >
<button wicket:id="save" type="submit" accesskey="s" > <wicket:message key="userEditPage.save" > <u >S </u >ave </wicket:message > </button >
</td >
</tr >
</table >
</fieldset >
</form >

</wicket:extend >

</body >
</html >

July 5, 2009

Good Java Open-Source Summary Site

Sometimes you come across good sites that you want to share with others. And today it happened I came across a good site that summaries a lot of Java open-source project. Which is a good starting page if you are looking for new Java library, for your new Java project. Enjoy!

http://java-source.net/