Navigator7 add-on: API of Vaadin 7 ?

An other little question :

is there a way not to set explicitly width of the window ?
I would like our application to fit the whole screen depending on resolution screen used at client side.
For the moment we use a fixed page width with this piece of code in inherited HeaderFooterFixedAppLevelWindow class

	protected ComponentContainer createComponents() {
		setPageWidth(200);
		return super.createComponents();
	}

Thx

You probably want to have your page to take the width of the browser window (as a normal Vaadin application in fact).

You need to create a class FloatAppLevelWindow extend NavigableAppLevelWindow,
and eventually a HeaderFooterFloatAppLevelWindow extend FloatAppLevelWindow (if you need Header/Footer).
These should be part of Nav7 (you are welcome to send them back to me when done, I’ll integrate them).

Then in your project, your class MyAppLevelWindow extends HeaderFooterFloatAppLevelWindow.

In FloatAppLevelWindow there is no pageWidth attribute.
The method


    protected void prepareInnerBand(Component innerComponent) {
        innerComponent.setWidth("100%");
    }

sets the width at 100%.

Reply to this post:
http://vaadin.com/forum/-/message_boards/message/155212?_19_delta=10&_19_keywords=&_19_advancedSearch=false&_19_andOperator=true&cur=4#_19_message_226085

@Johannes:
v7.46 integrates these changes. It’s in the add-on repository.

It does not integrate page caching (other posts) as none of you confirmed the need 8o

Sorry for the delay.
John.

Hi John,

I’ve downloaded the latest version of the Navigator (7.46) yesterday, and found that I could not run the demo application. I was getting “Unresolved compilation problems:” exceptions from NavigableApplicationServlet. This confused me greatly.

Cutting short quite a few hours of googling and .class reverse engineering, I found that the .class files in the navigator7.jar (v7.46) did not match the java source in the same jar. I extracted the source, and placed it into my own application (so that it compiled again), and the demo deployed correctly.

I think this is a packaging issue with v7.46 - I downloaded the previous version, v7.45, and the problem was not there.

Cheers,

Charles

@Charles Anthony

I’m terribly sorry for the time lost. I’ll republish it (v7.47) as soon as my Eclipse has been correctly reinstalled (probably tomorrow).

Thank you for reporting.

John.

I’ve reinstalled Eclipse and the plugins, tested Nav7 example application and re-exported.
It’s in the on-line add-on repository now as v7.47. Hope the packaging is better. Sorry for the delay.
I’m going to commit the source on google code too (in a minute).

Can’t find the 7.47 release, is it released yet ? Can see the commits on http://code.google.com/p/navigator7 but can’t find the jar in addon repo or anywhere else.

All the best, Pether

Yes, it was released, but … I did not push the “available” switch…
Sorry for this. You should see it in the addon repository now.

I’m confirming the need for this feature :wink:
Hope that other people would be agree for this too :slight_smile:

Ok Anthony.

I suggest the scope attribute in the @Page annotation:

@Page(scope="session")

Theoretically, possible scopes could be:

  • visible
  • window
  • session
  • application

Visible scope would be the default value and means, “the page currently visible”. That’s how Nav7 works now. It would set the page in no explicit cache, it’s just in the current Vaadin Window.

Window scope would be bound to the open tab. If a user comes back on a page from that tab, we would reuse the stored instance. Don’t know if this level would be useful. This corresponds to the Vaadin “Window” notion.

Session scope would be bound to the HttpSession, wich is currently named “Application” in Vaadin. It would be for that user, all tabs and browser windows shared (hope they will rename Window, Application & co in version 7).

Application scope would be the ServletContext. It would be a page reused for all users (as a home page for example).

The last 2 levels (Session and Application) would require changes in the Vaadin structure as because now a Page is a Component inside one (and only one) Window.

We’d also need the timeout attribute.

@Page(timeout=60*60*2)  // 2 hours

It would be the amount of seconds for keeping that page in cache without renewing (reinstantiating) it.

As implementation, of the “window” scope, I would probably change PageInvocation.getPageInstance() method.


    public synchronized Component getPageInstance() {
        if (pageInstance == null) {
            try {
                // instantiate page like: auctionPage = new AuctionPage();
                pageInstance = (Component) pageClass.newInstance();
                isInstanceNew = true;
            } catch (Exception e) {
                RuntimeException e2 = new RuntimeException("Problem while instantiating page class ["+pageClass+"]
. Probably bug. Does your page class have a no-arg constructor?", e);
                placeExceptionPage(e2);
                throw e2;
            }
        }
        return pageInstance;
    }

In the if pageInstance == null, I’d start with looking for the page in the cache.

We’d probably need a new PageCache class to manage the caching.
It would have a method “getPage(Class<? extends Component)” that returns a page or null.

The getPage method would look in the NavigableAppLevelWindow instance (getCurrent). NavigableAppLevelWindow would have a Map<Class<? extends Component>, DateAndComponent> cachedPages with the cached pages.
DateAndComponent would be a public static inner class of PageClass just holding a Date and Component value (2 attributes) together. Date is needed for the timeout.

We’d probably need to manage the page.getParent() attribute also. Only one page at a time can be NavigableAppLevelWindow.pageContainer at a time (=> not all the pages of the cache…)

Any volounteer to implement that?
I’ll be happy to review the code. Start from the SVN repository (v7.48).

John.

Thx for your feedback,

I like this approach,

I think for the moment, we only need saved page in a session scope view as it’s best suitable for application willing to be like a “rich application” as I think vaadin want to be like this.
We also don’t manage different tabs.

In our application all pages are represented as “modules” and each time a user want to switch from one module to an other he does’nt want to loose informations represented in the last module (or doesn’t want to filter again…).

For the moment I don’t really know if i’m enought skilled to improve this as i’m only a java developper and all that keep in touch with sessions or webapplication is quite cloudy for me ^^

Regards,

Anthony

@Anthony

Session scope with 1 tab = tab scope :wink:

As far as I know, it is not possible to put the same component (page instance) into 2 different Vaadin Windows (Nav7 AppLevelWindows). FYI, there in one Window instance per tab.
Concretely, it means that if a user would have 2 tabs open (2 Vaadin Window), he could not display the same page instance in both tabs (Vaadin Window) at the same time, because that page.getParent() returns one and only one Window (indirectly, through NavigableAppLevelWindow.pageContainer).

With the tab scope, there would be one page instance per tab. If you have only one tab, it means 1 page instance.

Have a good day.
John.

Hi John,

I’m trying to add some batch job configured by Spring, but I don’t really know how to set up this.
Without using Navigator I would use a servlet listener and set up contextInitialized and contextDesxtroyed of the class implementing servletContextListener.

In contextInitialized method I just put

	ServletContext ctx = arg0.getServletContext();
		WebApplicationContext springContext = WebApplicationContextUtils.getWebApplicationContext(ctx);
		batchCourriel = (RunnableBatch) springContext.getBean("batch-mail");
		batchCourriel.run();

And in contextDestroyed

this way, the batch is well handled

But when using Navigator, I think I have to use WebApplication class.

How would you configure that accessing Spring via WebApplication class ?

It seems also WebApplication class is only instanciate when the first user is connecting to the application but not before contrary to a listener class.

Thanks,

Hi Anthony,

You ask an interesting question, and I need more details. Here are some elements of answer.

WebApplication.init(…) is called from NavigableApplicationServlet.init(…).
That servlet is initialized when the first request arrives for it (when the 1st request comes in for Vaadin).
I’ve followed the way Vaadin 6 works on that perspective. As you, I think it would make more sense to do it a ServletContextListener. Hope that Vaadin 7 will do that and add the notion of WebApplication. They have not started thinking about it yet unfortunately, they are busy on v6.5.

Usually, in our batch jobs, we don’t need Vaadin at all, we don’t refer it and Vaadin could not have been initialized yet: no problem.

Why do you need the batch job? And when?

As its name suggests, it is for e-mails.
We also have batch jobs sending e-mails, and there we had a problem (as described on this threads a few posts ago): we would like insert links to pages in our mails.

In, I don’t remember which version, I fix this problem and the following code works even if Navigator 7 has not been initialized :-))))


    private String getTodoDetailEMailText(CourseTodo todo) {
        SectionText sectionTextEN  = sectionTextDao.getLastVersion(todo.getSection(), Language.EN);
        Course course = todo.getSection().getCourse();
        
        String courseUrl = BlackBeltUriAnalyzer.getFullUrl( new ParamPageResource(CoursePage.class, course) );
        String sectionUrl = BlackBeltUriAnalyzer.getFullUrl( new CoursePagePageResource(todo.getSection()) );
        String todoUrl = BlackBeltUriAnalyzer.getFullUrl(new ParamPageResource(SectionComparePage.class)
            .addParam("courseTodo", todo));
    
        return "<p>Todo " + todo.getId() + " - " + todo.getShortDescription() + "</p>"
            + "<p>course: <a href='" + courseUrl + "'>" + course.getName() + "</a>"
            + "section: <a href='" + sectionUrl + "'>" + sectionTextEN.getNumberedTitle() + "</a></p>"
            + "<p><a href='" + todoUrl + "'>Acess the Todo details</a></p>.";
        }

About how to start your batch jobs, I suggest you to not start them manually with a thread. We use Quartz. But if I had to start over, I’d probably try the new @Asynchronous Spring annotation.

Hope this helps.
John.

Thanks for you quick answer !

Maybe the problem I have is not really related to Navigator.

I had tried to use a servletContextListener but it seems it doesnt work when using Navigator (url generated to access navigator is broken)
That why i tried to use it inside webApplication.

Indeed I don’t need any kind of interaction between Vaadin and my job

If we can use Navigator, Spring and a basic ServletContextListener together I’ll do as u suggest.

Here is a piece of my web.xml when i tried using my batch throught a basic ServletContextListener


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app id="WebApp_ID">
	<display-name>TestWebapp</display-name>
	<!-- ApplicationServlet from Vaadin jar will respond to requests. -->
	<context-param>
		<param-name>productionMode</param-name>
		<param-value>false</param-value>
		<description>Vaadin production mode</description>
	</context-param>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:applicationContext.xml</param-value>
	</context-param>

	<!-- Spring listener -->
	<listener>
		<listener-class>
			org.springframework.web.context.ContextLoaderListener
		</listener-class>
	</listener>

	<!-- Batch listener -->
	<listener>
		<listener-class>
			com.logic.ecolect.core.batch.EnvoiCourrielServlet </listener-class>
	</listener>

<!-- Navigator Servlet -->
		
	<servlet>
		<servlet-name>ecolect</servlet-name>
		<servlet-class>org.vaadin.navigator7.NavigableApplicationServlet</servlet-class>
		<init-param>
			<param-name>application</param-name>
			<param-value>com.logic.ecolect.core.ui.EcolectNavigableApplication</param-value>
		</init-param>
		<init-param>
			<param-name>webApplication</param-name>
			<param-value>com.logic.ecolect.core.ui.EcolectApplication</param-value>
			<description>Navigator7 WebApplication class to start (optionnal)</description>
		</init-param>
	</servlet>



	<!-- Make the servlet respond to all requests. -->
	<servlet-mapping>
		<servlet-name>ecolect</servlet-name>
		<url-pattern>/*</url-pattern>
	</servlet-mapping>
	<resource-ref>
		<description>Resource reference to a factory for java.sql.Connection
			instances that may be used for talking to a particular
			database that
			is configured in the server.xml file.</description>
		<res-ref-name>jdbc/db</res-ref-name>
		<res-type>javax.sql.DataSource</res-type>
		<res-auth>Container</res-auth>
	</resource-ref>
</web-app>

I’m also quite new to Spring.
It seems ContextListener is a delegated class, so the problem may come from my multiple listener ?

ps : I’m using quarts also to manage some heavy job but didn’t wanted use it for this sample job as i don’t need to manage a scheduler, only executing the batch every x minutes.

I’m afraid that no one could help you without knowing the exact problem (stack trace?) and the whole code (batch included).

Hi John,

I did as u suggested and it works like a charme.

Here is a piece of code of HeaderFooterFixedAppLevelWindow :


import org.vaadin.navigator7.window.HeaderFooterFixedAppLevelWindow;
import com.vaadin.ui.Component;

public abstract class HeaderFooterFloatAppLevelWindow extends
HeaderFooterFixedAppLevelWindow {

	private static final long serialVersionUID = 9180881950850133308L;

	public HeaderFooterFloatAppLevelWindow() {
		super();
	}
	protected void prepareInnerBand(Component innerComponent) {
		super.prepareInnerBand(innerComponent);
		innerComponent.setWidth("100%");
	}
}

Maybe u can include it in your core add-on ?

Thank you Anthony, I just committed the code. It will be in the next version of the add-on.

I’ve gathered some requirements from the forum, that we want in Vaadin 7 navigation. Don’t hesitate to suggest more in this forum.

http://code.google.com/p/navigator7/wiki/RequirementsForVaadin7

I’m tring to use Navigator and I’ve a question about it.
In my application I build pages dinamically and then I don’t know “a priori” pages names and how many pages I’ve.
Could You explain me how I shoud I define such situation to Navigator ?
Tks
Tullio