KDubb FutureComponent
Unleash raw, multithreaded, asynchronous fury with FutureComponent. Especially useful when you present data from datasources
While that red indicator is spinning and spinning your users are losing interest.
Unleash raw, multithreaded, asynchronous fury with FutureComponent.
If you use datasources or have any components prepared using long running processes FutureComponent is here to help. With FutureComponent the user will get instant feedback with a waiting indicator where your component will be. When it has been created, it will automatically be shown to the user with no extra effort on your part. Just fire and forget.
Not only does it show the user feedback instantly, but will finish quicker by allowing you to easily multithread these tasks. Normally component1 will have to be completely prepared before component2 starts being worked on, but not with your trusty friend FutureComponent.
Sample code
import java.util.Properties; import java.util.concurrent.Callable; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServletRequest; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletContextHandler; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.kdubb.futurecomponent.factory.DefaultFutureFactory; import com.kdubb.futurecomponent.factory.FutureFactory; import com.vaadin.server.DeploymentConfiguration; import com.vaadin.server.VaadinRequest; import com.vaadin.server.VaadinServlet; import com.vaadin.server.VaadinServletRequest; import com.vaadin.ui.Button; import com.vaadin.ui.Component; import com.vaadin.ui.Label; import com.vaadin.ui.Table; import com.vaadin.ui.UI; import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.Window; import com.vaadin.ui.Button.ClickEvent; @SuppressWarnings("serial") public class TestApp extends UI { public static void main(String[] args) throws Exception { startInEmbeddedJetty(); } public static Server startInEmbeddedJetty() throws Exception { Server server = new Server(8888); ServletContextHandler handler = new ServletContextHandler(ServletContextHandler.SESSIONS); handler.addServlet(Servlet.class, "/*"); server.setHandler(handler); server.start(); return server; } // mapping used to if demo war is built from these sources @WebServlet(urlPatterns = "/*") public static class Servlet extends VaadinServlet { @Override public VaadinServletRequest createVaadinRequest(HttpServletRequest request) { VaadinServletRequest result = super.createVaadinRequest(request); DeploymentConfiguration conf = result.getService().getDeploymentConfiguration(); Properties params = conf.getInitParameters(); params.setProperty("UI", TestApp.class.getName()); return result; } } @Override protected void init(VaadinRequest request) { ApplicationContext context = new ClassPathXmlApplicationContext("spring/main.xml"); final FutureFactory futureFactory = (FutureFactory)context.getBean(DefaultFutureFactory.class); setSizeFull(); VerticalLayout layout = new VerticalLayout(); layout.setSpacing(true); layout.setMargin(true); { Button button = new Button("Normal Window"); button.addClickListener(new Button.ClickListener() { @Override public void buttonClick(ClickEvent event) { Window window = getNormalWindow(); UI.getCurrent().addWindow(window); } }); layout.addComponent(button); } { Button button = new Button("Futurized Window"); button.addClickListener(new Button.ClickListener() { @Override public void buttonClick(ClickEvent event) { Window window = getFutureWindow(futureFactory); UI.getCurrent().addWindow(window); } }); layout.addComponent(button); } this.setContent(layout); } private Component getLabel(String text) { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } return new Label(text); } private Component getTable() { try { Thread.sleep(2500); } catch (InterruptedException e) { e.printStackTrace(); } Table table = new Table(); table.setWidth("100%"); table.setPageLength(5); table.addContainerProperty("First Name", String.class, null); table.addContainerProperty("Last Name", String.class, null); table.addContainerProperty("Year", Integer.class, null); /* Add a few items in the table. */ table.addItem(new Object[] { "Nicolaus","Copernicus",new Integer(1473)}, new Integer(1)); table.addItem(new Object[] { "Tycho", "Brahe", new Integer(1546)}, new Integer(2)); table.addItem(new Object[] { "Giordano","Bruno", new Integer(1548)}, new Integer(3)); table.addItem(new Object[] { "Galileo", "Galilei", new Integer(1564)}, new Integer(4)); table.addItem(new Object[] { "Johannes","Kepler", new Integer(1571)}, new Integer(5)); table.addItem(new Object[] { "Isaac", "Newton", new Integer(1643)}, new Integer(6)); return table; } private Window getNormalWindow() { Window window = createNewWindow(); window.setCaption("Normal Window"); VerticalLayout layout = new VerticalLayout(); layout.setSizeFull(); layout.setSpacing(true); layout.setMargin(true); { Component component = getLabel("I took 1 second to generate"); layout.addComponent(component); } { Component component = getTable(); layout.addComponent(component); layout.setExpandRatio(component, 1); } { Component component = getLabel("Also took 1 second to get back"); layout.addComponent(component); } { Component component = getTable(); layout.addComponent(component); layout.setExpandRatio(component, 1); } window.setContent(layout); return window; } private Window getFutureWindow(FutureFactory futureFactory) { Window window = createNewWindow(); window.setCaption("Window with FutureComponents"); VerticalLayout layout = new VerticalLayout(); layout.setWidth("100%"); layout.setHeight("360px"); layout.setSpacing(true); layout.setMargin(true); { Component component = futureFactory.getFutureComponent(new Callable<Component>() { @Override public Component call() throws Exception { return getLabel("I took 1 second to generate"); } }); layout.addComponent(component); } { Component component = futureFactory.getFutureComponent(new Callable<Component>() { @Override public Component call() throws Exception { return getTable(); } }); layout.addComponent(component); layout.setExpandRatio(component, 1); } { Component component = futureFactory.getFutureComponent(new Callable<Component>() { @Override public Component call() throws Exception { return getLabel("Also took 1 second to get back"); } }); layout.addComponent(component); } { Component component = futureFactory.getFutureComponent(new Callable<Component>() { @Override public Component call() throws Exception { return getTable(); } }); layout.addComponent(component); layout.setExpandRatio(component, 1); } window.setContent(layout); return window; } private Window createNewWindow() { Window window = new Window(); window.setModal(true); window.setWidth("600px"); window.setHeight("460px"); return window; } }
Component component = futureFactory.getFutureComponent(new Callable<Component>() { @Override public Component call() throws Exception { Thread.sleep(1000); return new Label("I took 1 second to generate"); } });
<bean id="executor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> <property name="corePoolSize" value="5" /> <property name="maxPoolSize" value="10" /> <property name="queueCapacity" value="25" /> </bean> <bean id="futureFactory" class="com.kdubb.futurecomponent.factory.DefaultFutureFactory"> <property name="executor" ref="executor" /> </bean>
Links
Compatibility
Was this helpful? Need more help?
Leave a comment or a question below. You can also join
the chat on Discord or
ask questions on StackOverflow.
Version
- Released
- 2013-01-14
- Maturity
- EXPERIMENTAL
- License
- Apache License 2.0
Compatibility
- Framework
- Vaadin 7.0+
- Browser
- Browser Independent