Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Adds a VaadinRequestInterceptor abstraction #17502

Merged
merged 10 commits into from
Sep 26, 2023

Conversation

marcingrzejszczak
Copy link
Contributor

Description

VaadinFilter simulates an around aspect around processing of a request. Prerequisite for #17494

Related to #17436

Type of change

  • Bugfix
  • Feature

Checklist

  • I have read the contribution guide: https://vaadin.com/docs/latest/guide/contributing/overview/
  • I have added a description following the guideline.
  • The issue is created in the corresponding repository and I have referenced it.
  • I have added tests to ensure my change is effective and works as intended.
  • New and existing tests are passing locally with my change.
  • I have performed self-review and corrected misspellings.

Additional for Feature type of change

  • Enhancement / new feature was discussed in a corresponding GitHub issue and Acceptance Criteria were created.

@mshabarov mshabarov added the Contribution PRs coming from the community or external to the team label Aug 25, 2023
@marcingrzejszczak marcingrzejszczak changed the title Adds a VaadinFilter abstraction feat: Adds a VaadinFilter abstraction Aug 25, 2023
@marcingrzejszczak
Copy link
Contributor Author

Quick comment on the VaadinFilter (although now in separate PR): maybe it could also cover UI.access calls coming from separate threads 🤔 And then requests & al are optional or within some context parameter 🤷‍♂️

@mstahv can you elaborate on that?

Copy link
Contributor

@mshabarov mshabarov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me in general.
Two concerns about naming of this new class and the fact that both servlet and service has these filters mutable.
If possible, I would preference to have immutable collection once it is initialised.
I will check how it can be done.

@github-actions
Copy link

github-actions bot commented Aug 30, 2023

Test Results

1 007 files  ±  0  1 007 suites  ±0   1h 14m 21s ⏱️ + 13m 6s
6 420 tests +  2  6 379 ✔️ +  2  41 💤 ±0  0 ±0 
6 677 runs  +19  6 629 ✔️ +19  48 💤 ±0  0 ±0 

Results for commit 3a85d40. ± Comparison against base commit cb63006.

♻️ This comment has been updated with latest results.

@marcingrzejszczak
Copy link
Contributor Author

@mshabarov I've checked the Service init mechanism that you mentioned and decided to rewrite my proposal to use that mechanism. You can check the details here. I like it better because there is just 1 way of setting the interceptors common for spring and non-spring apps. PTAL

@mstahv
Copy link
Member

mstahv commented Aug 31, 2023

Explaining my comment regarding the UI.access & requests:

  • Not every change in Vaadin UIs happen with an active http request
  • UIs can be modified by via other users request or by external threads as well
  • UIs are then actually updated by the next XHR or via constantly open web socket communication
  • For app developers it would/could be handy if they could hook into begin and end of a "UI access", which are typically wrapped in calls passed to UI.access calls, unless they already happen within a "UI thread". One could for example open and close user specific backend/database connection or do various profiling related tasks

I didn't look through the change proposal thoroughly, but by quickly skimming it through (mostly checkin names of new classes), this would help only with common XHR connections and user originated UI access 🤔

@marcingrzejszczak
Copy link
Contributor Author

From my perspective we need to wrap all the entry points to the backend and everything going out of the backend. If we can control what goes into and out of the UI that would be perfect. Once we have such a list of entry and exit points I can instrument them (or at least try to :) )

@mstahv
Copy link
Member

mstahv commented Aug 31, 2023

Yeah, I'd like to claim that it is not very rare that interesting things (regarding observability/profiling) happens in these other kind of UI access calls. It for sure does not happen in every app, but for example in dashboard like apps, a lot.

@mshabarov
Copy link
Contributor

mshabarov commented Sep 4, 2023

It makes sense to me what Matti said about having hooks for UI.access.

VaadinService has runPendingAccessTasks where we can hook and call request interceptors before and after calling UI access pending futures. VaadinRequestInterceptor can be extended with extra methods for UI.access.

For Vaadin Push connections (communications via WebSockets), the requestStart and requestEnd methods are already being called for every request from client, see PushHandler::callWithUi method.

Copy link
Contributor

@mshabarov mshabarov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My previous comments are fixed, awesome work! 👍
Three points I would like to fix and clarify before we could merge it:

  • Wrapping UI.access calls with vaadin request interceptor to be able to add instrumentations for it (discussed it already with Matti T. in the comments above)
  • Cover ErrorHandler calls, so that the exceptions thrown in the UI update callbacks in the user's codes would be also wrapped and observable (see my comment below)
  • Maybe more global question: should we follow the same instrumentation list as we do for Vaadin Observability Kit, e.g. all Vaadin-provided request handlers, static file handler, data communicator and so on.
    My vision is that we can do it iteratively, so we can apply this pull request, add instrumentation (another opened PR) for it and then extend VaadinRequestInterceptor step-by-step with extra methods for concrete instrumentations and egress points.
    What do you think @heruan and @Legioth ?

@@ -1544,6 +1582,18 @@ private void handleExceptionDuringRequest(VaadinRequest request,
vaadinSession.lock();
}
try {
try {
vaadinRequestInterceptors
Copy link
Contributor

@mshabarov mshabarov Sep 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handleExceptionDuringRequest doesn't actually handle all the errors during request processing.
It catches internal errors, but errors that might happen inside lambdas provided by developers (mainly UI updates, for instance, if you pass an UI update into beforeClientResponse) are processed by ErrorHandler, so that the exception is not thrown up to the invocation hierarchy, but handled by this error handler. See https://vaadin.com/docs/latest/advanced/custom-error-handler.

This might be a default error handler or a custom error handler, which, for example shows the notification with error message or changes component's styles.

Also, if you search in the project by string .getErrorHandler().error(, you will find a few entries in the core code that catch exceptions and delegate them to the error handler.

Thus, to cover also the exceptions handled by ErrorHandler objects, we may add a ErrorHandlerWrapper that takes ErrorHandler in VaadinSession::setErrorHandler and decorates it with calls to request interceptors.

@marcingrzejszczak
Copy link
Contributor Author

Wrapping UI.access calls with vaadin request interceptor to be able to add instrumentations for it (discussed it already with Matti T. in the comments above)

I was thinking that we could instrument com.vaadin.flow.server.VaadinService#runPendingAccessTasks. But we would have to instrument using a different interceptor. The VaadinRequestInterceptor is really related to http. Here we could have an interceptor around executing commands. Would that make any sense?

Cover ErrorHandler calls, so that the exceptions thrown in the UI update callbacks in the user's codes would be also wrapped and observable (see my comment below)

If we did this via the interceptor that I mentioned above we would also take care of the error handling?

Maybe more global question: should we follow the same instrumentation list as we do for Vaadin Observability Kit, e.g. all Vaadin-provided request handlers, static file handler, data communicator and so on.
My vision is that we can do it iteratively, so we can apply this pull request, add instrumentation (another opened PR) for it and then extend VaadinRequestInterceptor step-by-step with extra methods for concrete instrumentations and egress points.
What do you think @heruan and @Legioth ?

I am all for baby steps ;)

@mshabarov
Copy link
Contributor

mshabarov commented Sep 15, 2023

I was thinking that we could instrument com.vaadin.flow.server.VaadinService#runPendingAccessTasks. But we would have to instrument using a different interceptor. The VaadinRequestInterceptor is really related to http. Here we could have an interceptor around executing commands. Would that make any sense?

Yes, this makes sense to me to add a new aspect for pending access invocations. Let's do it in a separate pull request.

If we did this via the interceptor that I mentioned above we would also take care of the error handling?

UI.access and whatever server side code that can pass through the ErrorHandler are quite unrelated to each other.
UI.access refers to a PUSH functionality, i.e. asynchronous server-to-client UI updates, whereas ErrorHandler intercepts server-side exceptions, including (but not only limited to UI.access), exceptions in synchronous handlers, like "before client response" commands and RPC requests from clients.

From the other hand, when the ErrorHandler::error method is called, it doesn't know from what context it's called, and this is correct. This means that we cannot easily decide which interceptor to call, when this error handler is called: request or async interceptor. If we skip intercepting error handler :: error calls, UI update codes in command would be ignored by these interceptors and not instrumented, which will make user of this API upset a lot.

A simplest solution IMO is to make a decorator for error handler, whenever it is being added to the session here

public void setErrorHandler(ErrorHandler errorHandler) {
, put there a call to VaadinRequestInterceptor::handleException. This would intercept also errors for async updates. Yes, this might be a bit confusing for API users, but I see no better and easy solution at the moment.

I am all for baby steps ;)

We discussed the design internally, and our decision now is to focus on the basic request/response instrumentation, not trying to repeat all the features implemented with OpenTelemetry standard in Vaadin Observability Kits, because it would need a really deep code changes in some cases. This definitely better to do in a separate pull requests later. For most of the users even having a request/response/error instrumentation is already a big feature.

* @author Marcin Grzejszczak
* @since 24.2
*/
public class VaadinRequestInterceptorServiceInitListener
Copy link
Contributor

@mshabarov mshabarov Sep 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By the way, why do we need this init listener?
Looks like doing this way, we make an extra loop forcing Flow to take a detour, whereas this can be "hardcoded" here

event.getAddedRequestHandlers().forEach(handlers::add);
, the same way as for request handler.

This might lead to not being able to autowire the interceptors as a Spring bean, but I believe this would be fine, you can still create a VaadinRequestInterceptorServiceInitListener and say that it should be a AtComponent in Spring based apps.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean I think I was following what was being done now for RequestHandlers. I've actually copy pasted the whole code that the request handlers are following and did the same for interceptors.

My analysis:

  • A request interceptor List<RequestHandler> handlers = createRequestHandlers(); is initialized. These handlers do not require any collaborators (they have default constructors only, which will not be the case when doing instrumentations - you need tracers, registries etc.)
    • I'm doing exactly the same for the interceptors List<VaadinRequestInterceptor> requestInterceptors = createVaadinRequestInterceptors();
  • when VaadinService is initialized it calls instantiator.getServiceInitListeners().forEach(listener -> listener.serviceInit(event)); what will initialize the event with whatever the listeners want to add (e.g. custom interceptors etc.). The custom listeners would set interceptors such as the micrometer observation interceptor
    • I'm doing the same for interceptors - I read the entries from the event and add them to an unmodifiable list
    • For the compatibility with Spring I've added a second constructor for constructor injection

I don't understand what I should actually do then if not what I've already done

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me checkout your fork and try to refactor it without making VaadinRequestInterceptorServiceInitListener. Will be back to you soon.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, thanks for being patient :)
I checked out your fork ("vaadinFilter" branch) and made the following changes on top of it:

  1. Removed changes in Instantiator, DefaultInstantiator and SpringInstantiator
  2. Removed VaadinRequestInterceptorServiceInitListener
  3. Removed META-INF/services file for VaadinRequestInterceptorServiceInitListener
  4. Removed VaadinRequestInterceptorServiceInitListener from SpringBootAutoConfiguration.
  5. Added an implementation for request interceptor impl to test-spring-boot test module:
@Component
public class LoggerRequestInterceptor implements VaadinRequestInterceptor {

    private static final Logger logger = LoggerFactory.getLogger("RequestInterceptor");

    @Override
    public void requestStart(VaadinRequest request, VaadinResponse response) {
        logger.info("Request start, path into = {}" , request.getPathInfo());
    }

    @Override
    public void handleException(VaadinRequest request, VaadinResponse response, VaadinSession vaadinSession, Exception t) {
    }

    @Override
    public void requestEnd(VaadinRequest request, VaadinResponse response, VaadinSession session) {
        logger.info("Request end, path into = {}" , request.getPathInfo());
    }
}
  1. Added initialiser to test-spring-boot test module:
@Component
public class MyVaadinServiceInitListener implements VaadinServiceInitListener {

    private final List<VaadinRequestInterceptor> interceptors;

    public MyVaadinServiceInitListener(@Autowired  List<VaadinRequestInterceptor> interceptors) {
        this.interceptors = interceptors;
    }

    @Override
    public void serviceInit(ServiceInitEvent event) {
        interceptors.forEach(event::addVaadinRequestInterceptor);
    }
}
  1. Changed some config in pom files to be able to quickly run the test app in test-spring-boot.

So now if you:

  1. Build the project with
    mvn clean install -DskipTests -pl flow-server,vaadin-spring,flow-tests/vaadin-spring-tests -am,
  2. Navigate to test module
    cd flow-tests/vaadin-spring-tests/test-spring-boot
  3. And finally run it with
    mvn clean spring-boot:run -nsu
  4. And navigate to "localhost:8888",

You will see the interceptor in action, adding some log message to the server console.

Why I prefer to remove these codes:

  1. Main reason is that I want to have a Micrometer implementation in a separate module, e.g. "flow-micrometer". Thus, the flow-server itself shouldn't add any interceptors by default, but flow-micrometer should - add the interceptors by adding the service init listener, like I showed above for MyVaadinServiceInitListener, as a Spring Bean.
  2. Service Init Listener API is for external usage (in the Vaadin projects, not inside Flow). Internally, we can and should hard-code the handlers/interceptors, added by default. In our case, the interceptors are empty by default. This might however change in the future, who knows what interceptors we might want to add by default.
    If we do it with adding a listener and adding SPI into meta-inf resources, it would mean a redundant loop in the code.
  3. Instantiator and Lookup additions doesn't seem clear - Flow can spot Service Init Listener without them. Service Init Listener can be found as a Spring Bean as a AtComponent, so no idea why we need an extra code for it.
  4. Not clear why SpringBootAutoConfiguration need a new bean (service init listener for interceptors). Again, you can create interceptors beans as I shown above in my example and autowire them to the listener class. All should work.

So, 2-4 seem to me an extra codes, interceptors API should work without it.
1 is proposed to be do in your second pull request.

Hope I haven't missed anything.

Here is IntelliJ IDEA patch that you can apply on your branch to see my codes (hope you are using IDEA :) )
remove_service_init_listener_and_add_a_usecase.patch

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks awesome! I mean we have the same outcome by having less code I'm all for it :D So how do we proceed now?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I cannot push into your branch, because I have no rights.
If you can apply my patch locally, could you commit it and push (only changes in flow-server and vaadin-spring, others are use case codes and local workarounds) it?
Also, tests I think need some tweaks, if you have a chance please do, otherwise I can help you with it.

@@ -119,6 +119,13 @@ public ServletRegistrationBean<SpringServlet> servletRegistrationBean(
return registration;
}

@Bean
public VaadinRequestInterceptorServiceInitListener vaadinRequestInterceptorServiceInitListener(
ObjectProvider<VaadinRequestInterceptor> interceptors) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On a second look this seems to me as an overhead.
We don't have a similar API/ability to add request handler and whatever objects developers can add in ServiceInitListeners.

Plus, projects which already have a service init listener can just add one line to their listener to add the interceptors.

See my another comment https://github.com/vaadin/flow/pull/17502/files#r1327153517.

So, if you have no big objections, I would propose to remove this from autoconfiguration for simplicity.

Copy link
Contributor Author

@marcingrzejszczak marcingrzejszczak Sep 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't have a similar API/ability to add request handler and whatever objects developers can add in ServiceInitListeners.

I mean you do, ServiceInitListener works via SPI and it can append things to the init event. I thought that it's done exactly for this purpose (https://vaadin.com/docs/latest/advanced/service-init-listener).

I can do whatever you want but I don't know how you would like this to work :) How will you want to add the request interceptors to the VaadinService?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is my vision of design so far:

  • flow-server creates an empty list of interceptors by default and makes this protected, so developers can change it if they want. In the future we might want to add some interceptors by default (for whatever purpose). flow-server collects interceptors from ServiceInitEvent and makes an immutable collection that is used for further http request interception. (this is already done and look awesome).
  • flow-micrometer module in the Flow repo adds a VaadinRequestInterceptorServiceInitListener as a Spring'sAtComponent and injects there all needed Micrometer Interceptors. No SPI registration is needed. If this module is in the classpath of the project, this listener should be picked and executed by Flow.
  • Vaadin plain projects can register their own service init listeners with SPI and Vaadin Spring-based projects can register this listener as a component and autowire interceptors.
  • No changes to Instantiator and SpringBootAutoConfiguration is needed for the above points to work.

Copy link
Contributor

@mshabarov mshabarov Sep 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your solution so far seems to make it possible to only add the interceptors beans in the projects (without care about making own service init listener).
I would strongly recommend to not do it within this pull request.
It should be a separate feature and consistent with other kind of data in the service init event.
So far I would state that the request interceptors, as request handlers, should be always added through a service init listener defined in the project.

@marcingrzejszczak
Copy link
Contributor Author

Yes, this makes sense to me to add a new aspect for pending access invocations. Let's do it in a separate pull request.

While waiting for feedback I started playing around with this concept and I got sth like this out of it (check the CommandInterceptor)
https://github.com/marcingrzejszczak/flow/compare/vaadinFilter...marcingrzejszczak:flow:vaadinCommandInterceptor?expand=1 , the only problem I had was that when I added that to an application not a single time did my interceptor got called (but maybe I did sth wrong).

What I'm currently thinking about is that we already have instrumentation coming form the Spring Web instrumentation (https://github.com/spring-projects/spring-boot/blob/v3.1.3/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/web/servlet/WebMvcObservationAutoConfiguration.java#L82-L96) of the incoming requests. So if we have a Vaadin application that is non-Spring definitely this new, server side instrumentation ( makes a lot of sense. In the Spring world we need to have IMO one or the other unless I'm missing sth.

@mshabarov
Copy link
Contributor

While waiting for feedback I started playing around with this concept and I got sth like this out of it (check the CommandInterceptor)

Great! Thanks for the enthusiasm 👍 🥇
I propose to make a separate PR for it, it would be much more easier.

@mshabarov
Copy link
Contributor

mshabarov commented Sep 20, 2023

@marcingrzejszczak So I propose to apply my last patch #17502 (comment), adapt the tests for it and then I propose to merge this PR, because it's going to be endless otherwise :)

Then we can consider making a new module for instrumentation and then continue with command interceptor.

@marcingrzejszczak
Copy link
Contributor Author

I've just applied the patch, let's see how the build goes...

@vaadin-bot vaadin-bot added +0.1.0 and removed +1.0.0 labels Sep 25, 2023
@mshabarov
Copy link
Contributor

Please run mvn formatter:format to let the format checker step pass.

Copy link
Contributor

@mshabarov mshabarov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implementation looks good to me.
A few comments about leftover codes and imports, and one comment about test.

import java.util.ServiceLoader;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please revert these changes. This class doesn't have a meaningful additions now.

@@ -31,6 +27,10 @@
import com.vaadin.flow.server.communication.IndexHtmlRequestListener;
import com.vaadin.flow.server.communication.UidlWriter;

import java.io.Serializable;
import java.util.ServiceLoader;
import java.util.stream.Stream;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please revert these changes. This class doesn't have a meaningful additions now.

import com.vaadin.flow.router.RouteData;
import com.vaadin.flow.router.Router;
import com.vaadin.flow.server.HandlerHelper.RequestType;
import com.vaadin.flow.server.communication.*;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't use the wildcard import, but specify the exact classes, like it was before.

</execution>
</executions>
</plugin>
<!-- <plugin>-->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revert this. It is a leftover from a local run.

<groupId>com.vaadin</groupId>
<artifactId>vaadin-dev-server</artifactId>
<version>${project.version}</version>
</dependency>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same. Please revert this. It is a left over from local test.

@@ -112,7 +118,7 @@
<execution>
<goals>
<goal>prepare-frontend</goal>
<goal>build-frontend</goal>
<!-- <goal>build-frontend</goal>-->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same. Please revert this. It is a left over from local test.


import jakarta.servlet.MultipartConfigElement;
import java.util.HashMap;
import java.util.Map;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revert imports change, no functionality is added into this class.

@@ -89,4 +95,21 @@ public void uiInitListenerAsSpringBean_listenerIsAutoregisteredAsUIInitiLietnerI
Assert.assertSame(ui, listener.events.get(0).getUI());
}

@Test
public void requestInterceptorsAreRegisteredOnTheService()
Copy link
Contributor

@mshabarov mshabarov Sep 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure that I understand how this is supposed to work.
How MyRequestInterceptor instances get injected into VaadinService? I see no service init listener here.

Would it be more clear if you:

  1. Move LoggerRequestInterceptor and MyVaadinServiceInitListener classes from test-spring-boot module to here
  2. Add MyVaadinServiceInitListener to the Spring context (maybe this isn't even needed if Spring test configuration can recognise the bean and add it automatically), so this listener would pass through the VaadinService and it's interceptors are collected and added to the list by new logic in the flow-server.
  3. Pass any VaadinRequest to the VaadinServlet/VaadinService and check that the interceptor does changes in the request/response (like you already does in flow-server test).

Making this kind of test, we would repeat the use case of how these interceptors are added to Flow in reality.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this test fails with:

Error:  Tests run: 3, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.172 s <<< FAILURE! -- in com.vaadin.flow.spring.service.SpringVaadinServletServiceTest
Error:  com.vaadin.flow.spring.service.SpringVaadinServletServiceTest.requestInterceptorsAreRegisteredOnTheService -- Time elapsed: 0.035 s <<< FAILURE!
org.opentest4j.AssertionFailedError: There should be 1 filter ==> expected: <1> but was: <0>
	at org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:151)
	at org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:132)
	at org.junit.jupiter.api.AssertEquals.failNotEqual(AssertEquals.java:197)
	at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:150)
	at org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:560)
	at com.vaadin.flow.spring.service.SpringVaadinServletServiceTest.requestInterceptorsAreRegisteredOnTheService(SpringVaadinServletServiceTest.java:108)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honestly, after the changes you've made I don't know how this is supposed to work but I'm not a Vaadin expert ;) I'm trying to make the tests work now. Will ping you once I can't figure things out

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I've made the test pass, let me see if everything else is working fine and that formatting is not broken and I will push the changes! Your comments were very helpful.

Copy link
Contributor

@mshabarov mshabarov Sep 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, now this test clearly shows that MyRequestInterceptor is autowired to the listener component and gets used by VaadinService.

LoggerRequestInterceptor class is not needed I think. I suppose it is added to the list and invoked, but not used anyhow in tests.

So let's remove LoggerRequestInterceptor and I'm ready to approve the PR.

@marcingrzejszczak
Copy link
Contributor Author

Ok, hopefully everything is fine now. I do have problems with the wildcard imports and formatting because I can't seem to align with the intellij idea formatting style for this project. Anyways, hopefully that's resolved now

@@ -89,4 +95,21 @@ public void uiInitListenerAsSpringBean_listenerIsAutoregisteredAsUIInitiLietnerI
Assert.assertSame(ui, listener.events.get(0).getUI());
}

@Test
public void requestInterceptorsAreRegisteredOnTheService()
Copy link
Contributor

@mshabarov mshabarov Sep 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, now this test clearly shows that MyRequestInterceptor is autowired to the listener component and gets used by VaadinService.

LoggerRequestInterceptor class is not needed I think. I suppose it is added to the list and invoked, but not used anyhow in tests.

So let's remove LoggerRequestInterceptor and I'm ready to approve the PR.

marcingrzejszczak and others added 10 commits September 25, 2023 14:39
VaadinFilter simulates an around aspect around processing of a request

related to vaadingh-17436
* renamed VaadinFilter to VaadinRequestInterceptor
* Vaadin uses Lookup to init the VaadinService
** Added VaadinRequestInterceptors to ServiceInitEvent
** Added a VaadinRequestInterceptorServiceInitListener that will add interceptors to the init event
** The listener works with ServiceLocator based DI and Spring based DI (has both arg and non-arg constructor)
** That way we have 1 way of initializing the interceptors
* Added the VaadinRequestInterceptorServiceInitListener to META-INF for automated locator discovery
* Added the VaadinRequestInterceptorServiceInitListener as a bean for Spring Boot auto configuration
* Extended the Instantiator mechanism to find all instances of a given class
** Implemented the method in Spring and non-Spring implementations
Co-authored-by: Mikhail Shabarov <[email protected]>
@knoobie
Copy link
Contributor

knoobie commented Sep 25, 2023

Before it is forgotten, can we get the 24.2 label? ;)

@mshabarov
Copy link
Contributor

mshabarov commented Sep 25, 2023

Before it is forgotten, can we get the 24.2 label? ;)

I'm afraid no, because Flow 24.2 beta is out today and we lost the release train for it. I propose to target this and further instrumentation feature to Vaadin 24.3.

@mshabarov mshabarov changed the title feat: Adds a VaadinFilter abstraction feat: Adds a VaadinRequestInterceptor abstraction Sep 25, 2023
@sonarcloud
Copy link

sonarcloud bot commented Sep 25, 2023

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 0 Code Smells

No Coverage information No Coverage information
0.0% 0.0% Duplication

@mshabarov mshabarov merged commit 18e2851 into vaadin:main Sep 26, 2023
20 of 22 checks passed
@marcingrzejszczak marcingrzejszczak deleted the vaadinFilter branch September 26, 2023 08:17
@vaadin-bot
Copy link
Collaborator

This ticket/PR has been released with Vaadin 24.3.0.alpha1 and is also targeting the upcoming stable 24.3.0 version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done - pending release
Development

Successfully merging this pull request may close these issues.

5 participants