UIScope and service class

Hi everyone. I try to use @UIScope in my mainlayout class that store the menu to use in another
class some UI component of the mainlayout. Is it possible to use the UIScope implementation in service class ?
Like it’s explain in the doc, in a service class i implement on the constructor like that

@Service
public class ComposantTService
{
		
	public ComposantTService(@Autowired UIMainlayout argUiMainmayout)
	{

but on the compilation i have this error

***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 0 of constructor in com.steel.dao.ComposantService required a bean of type 'com.steel.UIMainlayout' that could not be found.


Action:

Consider defining a bean of type 'com.steel.UIMainlayout' in your configuration.

And I have define the class UIMainlayout

@UIScope
public class UIMainlayout {

	private Span msgBadge;
	private Dialog dlgNotif;
	private SteelButton btNotif;
	
	public UIMainlayout() {

Can you help me ?

Add another stereotype in your UIMainLayout like

- @Component
- @SpringComponent

Ok thanks for your help. I add this in my class and now another error

Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'UIMainlayout': Scope 'vaadin-ui' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton

(@Autowired annotation should not be mandatory)
Like Rubén mentioned, you need to register to the layout with @Component or @Service

To your newest error, I was just to write about this:
ComposantTService has a Application Scope (default), but UIMainLayout can only be created when a UI has been created. When the application starts, I think, all application scoped beans are created, but there is no UI yet that can be connected to UIMainlayout.

  • Either make ComposantTService UI scoped too,
  • or switch the dependence: UIMainlayout(@Autowired ComposantTService service)

You can’t inject UI Scoped Beans in a Singleton (ComposantTService)

OK :-( . It’s only that solution I have found (UIScope) to handle the mainlayout component in other class…

If you can describe your “real” problem we might be able to help with an appropriate solution. You normally don’t want to “hardwire” access to your main layout.

Ok. In my “MainLayout”, I’ve created a notification button. So in differrent view of my application,
I want to change the number display of my “notificatoin button”. That why I want to access of this component created in the “MainLayout”.

Your MainView could be a subscriber to these events.

When those events come to you, you will refresh or update your component.

Push mentioned above is not needed in your simple use-case. You can use this pattern How do I communicate between components attached to one UI - Vaadin Cookbook

I like this approach, but perhaps it applies broadcasting unduly at certain points.

Thank you for your help. I’m going to try the cookbook solution

I’m sorry but I don’t see how to solve my problem with the cookbook solution.
I understand in the example that when I click on an element of the Mainlayout (in my environment) I can handle other component. But my use case is when I click on element of other view, I want to change state of Mainlayout component.

Pseudo Code:

MyEvent(int number); 

View
  button(clickEvent -> publish new MyEvent(12));

MainLayout implements Subscribe<MyEvent>
 onEvent(MyEvent event -> // do something)

As long as your component/view is attached, you could also try findAncestor.
I hope this works like this:

// on click
UIMainlayout mainLayout = this/* the view */.findAncestor(UIMainlayout.class);
if (mainLayout != null) {
   mainLayout.myAction(params)
}

It’s a good idea but I try quickly in a view and mainlayout is always null :frowning:

put the code better and you can see it.

Maybe check your timings! These are my console prints:

contructor null
beforeEnter null
onAttach com.example.application.views.MainLayout@416f93b1
afterNavigation com.example.application.views.MainLayout@416f93b1

Thank you all of you for your help. For the moment the UIScope method work fine (I use only in viex not in service class). I will check next week the timing for your method @ladam

1 Like

If you want to access from the view to the layout then you can check this link: java - Vaadin Refer to mainLayout from RouterLayout - Stack Overflow

The main layout is usually the parent of the view or the child of the UI.

UI scope means the annotated component will be kept if you are on the same UI ( which is almost a browser tab). I don’t think it’s the solution for your problem.

1 Like