Spring integration helper class

Thanks for providing that clarity, Archie :slight_smile:

For what it’s worth I, too, have only found a limited use for session beans - in fact, just the one so far : an event bus for all views/presenters involved with a Vaadin Application. Note, not an web-application-wide event bus.

As far as I can see, everything else Spring configured is going to be a singleton.

Cheers,

Charles

Thanks for the samples, by the way.

The only thing I thought could be better about them is if they contained a very simple example of how you could wire Spring beans into more than just the Vaadin application. For example: how you would approach wiring Spring managed services into a Vaadin custom component.

Hello!

Thanks for this clean example! I’m new to Vaadin and I’m going to integrate it into my web applications I’m developing for my company.

I’m already using Spring, but there’s a thing I don’t understand of your example (demo2.zip).

The question is: is it necessary to use AutowireCapableBeanFactory?

If Spring is correctly configured in applicationContext.xml, when you get the WebApplicationContext with WebApplicationContextUtils.getRequiredWebApplicationContext you should be able to extract the MyApplication bean directly from it, no? Provided all injection via annotation and so on was correctly activated in the applicationContext itself.

Thanks in advance for any hint.

Cheers,

Fabio

For what I know, since you get the Application object created and injected by Spring itself, you get all other dependent object from there.

I mean: you define a custom component, marked for injection (via annotation) or declared in applicationContext and injected into the main Application bean.
Then, you can get that instance directly from the main Application code, isn’t it? And all Spring facilities should work as expected, for example the @Transactional annotation.

I don’t doubt that there may be a simpler way to do this.

Here is my (limited) understanding: The problem is that Vaadin requires you to extend Vaadin’s ApplicationServlet, which knows nothing of Spring. Every time ApplicationServlet needs a new Application instance, it invokes ApplicationServlet.getNewApplication(). This happens many times during the course of your web server’s life. This is the point at which we create Application instances, not when the application context is created. So what we have to do is create the Application instance using Spring at that time. That’s what the current code does.

Now it may be possible to define your bean as a scope=“prototype” (or scope=“session” more correctly) bean in the application context and have the BeanFactory get the bean by name instead of creating it explicitly. Then all the wiring would be done normally and implicitly. But you would also have to explicitly declare your Application bean in the application context. I guess it’s 6 one/half-dozen the other.

FYI, the AutowiringApplicationServlet is now available in a JAR
here
.

Now it’s all clear, thank you :slight_smile:

But my question remains: why do you use AutowireCapableBeanFactory? Couldn’t you use directly WebApplicationContext, calling getBean() on it?

Ok, maybe I’m getting to the point. I thought you can activate (as you did) Spring’s AOP-based configuration and then declare which beans are managed by Spring with annotations. So, besides putting @Autowired onto MyApplication’s fields, declaring the whole class as a Spring’s bean (with @Component, for example).

Anyway, the only reason you used AutowireCapableBeanFactory is to construct and correctly inject the MyApplication object, without the need to declare it in the applicationContext.xml?

Correct. This is the first approach. In retrosepct, the second approach probably makes more sense and is more “Spring-like”, i.e., less of a hack. At the time I was just trying to make the dumb thing work :slight_smile:

I see. Thank you. Please don’t misunderstand me: your example was illuminating, I was getting lost into all the documentations, javadocs and so on so you saved my weekend :wink:

I would expect that your Autowire servlet will be integrated directly into Vaadin distribution, in the main package or in an integration package, ready to use.

Cheers and thank you again!

Fabio

Here’s my take on Vaadin Spring integration
http://psponcoding.blogspot.com/2011/03/vaadin-spring-integration.html
. Depending on who you ask, but it might be a bit cleaner approach. The cleanest way would probably require some modifications to the core Vaadin implementation as suggested in the article.

I’m noticing that all approaches here are calling directly (one way or another) the Spring applicationContext for getting their beans through explicit invocation of the injection process.

Could it be possible to have Spring create every Vaadin component? So the DI would be done by Spring itself, without helper classes.

The only one I see necessary is the first Application creation (because of the lack of component creation listener). For this there’s need of the AutowiringApplicationServlet.

But from there on, couldn’t Spring be enough? If the main application object has all its dependencies injected by Spring itself and the main bean is Spring manager, what is missing?

Sure, that should work. E.g., you could have something like:

public class MyApp extends Application {

    @Autowired
    private Panel panel1;

   ....

where the Panel comes from the application context.

What you need to achieve this is
load-time weaving
: a way to inject dependencies into non-Spring managed beans.

This got me wondering and indeed there is a simpler way to do it as described above. With this scheme, no AutowireCapableBeanFactory is necessary (just WebApplicationContext) and your Application bean is declared explicitly inside the Spring application context (with scope=“session” of course).

See attached ZIP file.
11615.zip (13 KB)

Doh! You were faster then me :slight_smile:
I’ve just built a skeleton application exactly as your last example.

This way Spring and Vaadin integrates very smoothly!

Again, thank you for your support.

Best regards,

Fabio

Hi,
Thank you guys for resources provided here, and thanks for samples also.


In what situation I need load time weaving?

Let’s say I have SomeScreen class extending VerticalLayout in my app.
I have defined my main Application class as session scoped bean as in provided examples, but I create instance of SomeScreen with constructor during application lifecycle (not as spring bean).
I want use my repository bean from root app context as property inside SomeScreen

I tried following without load time weaving it doesn’t work. I receive NullPointerException for repository.


@Configurable(preConstruction = true,dependencyCheck=true)
public class SomeScreen extends VerticalLayout  {
	
	@Autowired(required = true)
	private SomeRepository repository;

root-context with :
<context:annotation-config />
<context:spring-configured />
<context:component-scan  />
<bean id="someRepository" class="example.WSSomeRepository"></bean>
<bean scope="session" class="MyVaadinApplication"/>

How can I achieve this without load time weaving? Or is it possible?
If not, do I need to define SomeScreen as another session scoped bean

In my experience with Spring I’ve never had occasion to use load time weaving, and moreover I’m not sure that I completely understand when or why it’s needed (that’s a statement about my own ignorance, not the usefulness of load-time weaving).

In any case, you should be able to figure out why your example doesn’t work by continuously morphing it into my example (demo3.zip) until it starts working.

Problem I encounter is that I can’t inject spring beans in any object except main application class.

I guess I need to define every object (mainly layouts) as spring bean?
@configurable in such classes doesn’t work :(, but I see it works in SpringApplication sample app in vaadin incubator repository.

I forgot to put aspectj compile time weaver plugin into pom, my fault.

Archie,

The servlet does not compile for me :


return this.getWebApplicationContext().getBean(applicationClass);

getBean expects a String not a class. Not sure what was intended there …

Jorg