Lazy Loading JSF DataTable

I’ve actually blogged about this topic three years ago and introduced the PagedListDataModel. That solution worked at that time with some flows in design but now after three years, I’ve a much better solution to the same problem. Using PrimeFaces DataTable it’s a piece of cake to load millions of data lazily, just set the lazy to true and provide a LazyDataModel. Here’s is how it works.

<p:dataTable var="car" value="#{tableBean.lazyModel}" paginator="true" rows="10"
			dynamic="true" lazy="true">

	<p:column>
		<f:facet name="header">
			<h:outputText value="Model" />
		</f:facet>
		<h:outputText value="#{car.model}" />
	</p:column>

	<p:column>
		<f:facet name="header">
			<h:outputText value="Year" />
		</f:facet>
		<h:outputText value="#{car.year}" />
	</p:column>

	<p:column>
		<f:facet name="header">
			<h:outputText value="Manufacturer" />
		</f:facet>
		<h:outputText value="#{car.manufacturer}" />
	</p:column>

	<p:column>
		<f:facet name="header">
			<h:outputText value="Color" />
		</f:facet>
		<h:outputText value="#{car.color}" />
	</p:column>
</p:dataTable>

And the lazyModel;

public class TableBean {

	private LazyDataModel<Car> lazyModel;

	public TableBean() {
		/**
		* Test with one hundred million records.
		* In a real application use an sql Count query to get the row count.
		*/
		lazyModel = new LazyDataModel<Car>(100000000) {

			/**
			 * Dummy implementation of loading a certain segment of data.
			 * In a real applicaiton, this method should access db and do a limit based query
			 */
			@Override
			public List<Car> fetchLazyData(int first, int pageSize) {
				logger.info("Loading the lazy car data between {} and {}", first, first+pageSize);

				List<Car> lazyCars = new ArrayList<Car>();
				populateLazyRandomCars(lazyCars, pageSize, first);

				return lazyCars;
			}
		};
	}

	public LazyDataModel<Car> getLazyModel() {
		return lazyModel;
	}

	private void populateLazyRandomCars(List<Car> list, int size, int first) {
		for(int i = 0 ; i < size ; i++) {
			int offset = i + first;
			list.add(new Car("Model_" + offset, getRandomYear(), "Brand_" + offset, "Color_" + offset));
		}
	}
}

That’s just it, whenever a paging event occurs with ajax, your fetchLazyData implementation will be called with the offset and pageSize. In a real application, you need to use your specific data access methods to load a chunk of data between a certain interval. For example in JPA api setMaxResults(pageSize) and setFirstResult(first) would do the trick. Also you need to define how many virtual records are there to be displayed so that PrimeFaces DataTable can create it’s paginator using that value, as an example a count/projection query could be used.

So to sum up, with PrimeFaces DataTable lazy loading capabilities even if you have billions of records, you can enable lazy loading very easily since number of all records are not relevant, only the records on the current datatable page is loaded.

There’s an online demo that demonstrates how to display one hundred million(100000000) records with this feature with paging happening less than a second.

PrimeFaces UI 0.9.3 Trailer

PrimeFaces UI 0.9.3 is coming soon with many new features and improvements, here’s the video of the trailer :)

“Rapid RIA with PrimeFaces” talk

On 6th of October, I’ll be doing my “Rapid RIA with PrimeFaces” talk at Skills Matter, London. This is a free event organized by London Java Web Users Group. See the announcement for more information and registration. Hopefully after the event, we’ll head over to the nearby pub for drinks and further discussion.

Posted in Developer, Java, PrimeFaces. Comments Off

Sample iPhone Apps with TouchFaces

For demonstration purposes I’ve created a couple of sample iPhone apps using TouchFaces. Here’s a short screencast explaining how these apps work and how easy it is to implement them with PrimeFaces.

These apps are deployed online so you can test them with your iphone or a webkit based mobile browser. Demo page also contains pointers to the source codes.

“Rapid RIA with PrimeFaces” slides

First of all thanks to EMC Conchango for inviting me to their communit day sessions, my talk was titled as “Rapid RIA Development with PrimeFaces”. You can find the slides of my presentation at PrimeFaces homepage documentation section. In october I’ll be doing an updated version of this talk at London Java Web Users Group.

Posted in Developer, Java, PrimeFaces. Comments Off

IPhone App Development with JSF

TouchFaces is a UI development kit to create IPhone web applications with JSF. TouchFaces is a member of PrimeFaces family and will be shipping with the UI module. Basically it allows developing applications using JSF with the native IPhone look and feel, plus it’s powered by PrimeFaces UI infrastructure and Ajax is built-in.

I’ll also publish detailed articles soon but recently I’ve created a screencast as a getting started tutorial. Enjoy!

Update: See sample iphone apps and mobile push for further information.

Growl meets JSF

Mac OS X’s growl is an intuitive way to display messages from the system and other apps. So how can you bring this way of notification to web with JSF. It’s as simple as;

<p:growl />

PrimeFaces Growl component simply replaces h:messages (lame) so growl is equipped with attributes such as showSummary, showDetail, globalOnly. Since growl displays FacesMessages severity information is provided with an icon that can be info, warn, error or fatal.

Picture 3Picture 2

You can even integrate growl with your ajax request, following is an example;

<p:growl id="messages"/>
<p:commandButton value="Save" update="messages" />

Online Demos
All sample applications of PrimeFaces use growl for notification here are some links;

ShowCase
BookStore
PhoneBook

Growl will also be integrated to PrimeFaces push support which is coming soon so all of a sudden clients can be notified of a message with Growl.

Easy Unit Testing JSF Backing Beans

It’s not secret that JSF is not the best testable web framework of all. When it comes to Unit Testing JSF backing(managed-bean) logic, the reason for this is quite obvious. At some point when programming the backend logic of your page, you need to use FacesContext to access FacesMessages, session or etc. So how this can be avoided?

PrimeFaces Optimus features an IOC container built on top of Google Guice that goes beyond the capabilities of JSF’s core IOC. Some of these are constructor&field injection, AOP support, easy testing.

To demonstrate how easy it’s easy to test JSF backing beans powered by Optimus, I’m going to implement a simple login scenario. There’re three classes involved in this example; LoginService, LoginServiceImpl and LoginController.

LoginService

public interface LoginService {

	public boolean login(String username, String password);

}

LoginServiceImpl

public class LoginServiceImpl implements LoginService {

	public boolean login(String username, String password) {
		//Connect to a datasource(ldap, db) and actually validate user
		//return outcome
	}

}

LoginService and it’s implementation are pretty straightforward. The important part is the LoginController, below is the untestable default way of implementing LoginController.

LoginController – Classic

public class LoginController {

	private String username;
	private String password;
	private LoginService loginService;

	//JSF can set through a managed-property
	public void setLoginService(LoginService loginService) {
		this.loginService = loginService;
	}

	public String loginClicked() {
		boolean isValidUser = loginService.login(username, password);

		if(isValidUser) {
			return "mainpage";
		} else {
			//Evil code that makes your backing bean untestable
			FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Invalid login", "Wrong username/password combination");
			FacesContext.getCurrentInstance().add(null, message);
			//End of evil code

			return "failed";
		}
	}

	public String getUsername() {return username;}
	public void setUsername(String username) {this.username = username;}

	public String getPassword() {return password;}
	public void setPassword(String password) {this.password = password;}
}

The problem above is by using FacesContext to add messages, you just made your code hard to test. At this point you can use shale test static mock library(the project is dead already) or change your code to remove FacesContext references. Here’s how to;

LoginController – Better


@Controller(name="loginController", scope=Scope.REQUEST)
public class LoginController {

	private String username;
	private String password;
	private LoginService loginService;
	private FacesMessages messages;

	@Inject
	public LoginController(LoginService loginService) {
		this.loginService = loginService;
	}

	@Inject
	public void setFacesMessages(FacesMessages messages) {
		this.messages = messages;
	}

	public String loginClicked() {
		boolean isValidUser = loginService.login(username, password);

		if(isValidUser) {
			return "mainpage";
		} else {
			messages.addError("Invalid login", "Wrong username/password combination");

			return "failed";
		}
	}

	public String getUsername() {return username;}
	public void setUsername(String username) {this.username = username;}

	public String getPassword() {return password;}
	public void setPassword(String password) {this.password = password;}
}

That’s it, now you don’t reference FacesContext any more, FacesMessages is a simple interface, you can inject it with @Inject. Although you can use Field injection to avoid a setter for simplicity but that’s just a bad practice regarding testing.

Finally here’s a simple test with JUnit and Mockito(My favorite mock library).

LoginControllerTest

import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.primefaces.examples.bookstore.service.LoginService;
import org.primefaces.examples.bookstore.view.LoginController;
import org.primefaces.optimus.application.FacesMessages;

public class LoginControllerTest {

	private LoginController controller;
	private LoginService loginService;
	private FacesMessages facesMessages;

	@Before
	public void setup() {
		loginService = mock(LoginService.class);
		facesMessages = mock(FacesMessages.class);

		controller = new LoginController(loginService);
		controller.setFacesMessages(facesMessages);
	}

	@After
	public void after() {
		controller = null;
	}

	@Test
	public void invalidCredentialsShouldStayOnLoginPageAndGiveMessage() {
		controller.setUsername("primo");
		controller.setPassword("1234");

		//stub
		when(loginService.login("primo", "1234")).thenReturn(false);

		//execute command action
		String result = controller.loginClicked();

		//outcome should be failed
		assertEquals("failed", result);

		//verify if message is added
		verify(facesMessages).addError("Invalid login", "Wrong username/password combination");
	}

	@Test
	public void correctCredentialsShouldLoginTheUser() {
		controller.setUsername("primo");
		controller.setPassword("4444");

		//stub
		when(loginService.login("primo", "4444")).thenReturn(true);

		//execute command action
		String result = controller.loginClicked();

		//outcome should be failed
		assertEquals("mainpage", result);
	}
}

In addition to FacesMessages, I’ve also added more solutions to commonly used stuff like Request Parameters or Session. Injection them is as easy as;


	@Inject
	private Params params;

	@Inject
	private Session session;

Whole idea is to abstract backing beans from any code(FacesContext) that makes testing harder and introduce more interfaces to code with.

PrimeFaces Dual Release

I’m pleased to announced that new versions of two PrimeFaces subprojects are released. UI Components 0.9.2 and Optimus 0.8.0 binaries are available at Prime Maven repository and project’s google code page.

UI Components 0.9.2

UI Components 0.9.2 includes important performance updates, new components and improvements on Partial Page Rendering infrastructure. Significant changes of this release are as following.

  • New component : Wizard
  • New component : Layout Framework
  • New component : Growl
  • New component : Stack
  • New component : Collector
  • Every resource that is included to the page is now compressed by YUI compressor, this leads to a significant improve in page load times.
  • Plain Html is now supported in partial response with Facelets.

Full changelog is availabe at here. Next version 0.9.3 will feature better portlet support, enhanced datatable and new components like dualList and keyboard.

Optimus 0.8.0

JPA and Persistence support is written to bridge JSF and Guice with warp-persist. Optimus simply orchestrates JSF-Guice-JPA stack. I’ve also added a bookstore sample application to demonstrate this lightweight but powerful stack in action.