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

fix: fix serialization issues (#438) #439

Merged
merged 2 commits into from
Jun 28, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
<cdi.api.version>2.0.SP1</cdi.api.version>
<javax.annotation.api.version>1.3.2</javax.annotation.api.version>
<junit.version>4.13.2</junit.version>
<mockito.version>4.2.0</mockito.version>
<mockito.version>5.4.0</mockito.version>
<maven.javadoc.version>3.3.1</maven.javadoc.version>
</properties>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import com.vaadin.flow.server.VaadinService;
import com.vaadin.flow.server.VaadinServletService;
import com.vaadin.flow.server.VaadinSession;
import com.vaadin.flow.server.WrappedSession;

import javax.enterprise.context.spi.Context;
import javax.enterprise.context.spi.CreationalContext;
Expand Down Expand Up @@ -86,7 +87,7 @@ public CdiVaadinServletService(CdiVaadinServlet servlet,

@Override
public void init() throws ServiceException {
delegate.init();
delegate.init(this);
super.init();
}

Expand All @@ -96,6 +97,20 @@ public void fireUIInitListeners(UI ui) {
super.fireUIInitListeners(ui);
}

@Override
protected VaadinSession loadSession(WrappedSession wrappedSession) {
return super.loadSession(wrappedSession);
}

@Override
protected void storeSession(VaadinSession session, WrappedSession wrappedSession) {
super.storeSession(session, wrappedSession);
}

private void restoreDelegate(VaadinSession session) {

}

public Optional<Instantiator> loadInstantiators() throws ServiceException {
BeanManager beanManager = delegate.getBeanManager();

Expand Down Expand Up @@ -146,21 +161,17 @@ public CdiVaadinServlet getServlet() {
*/
public static class CdiVaadinServiceDelegate implements Serializable {

private final VaadinService vaadinService;

private transient BeanManager beanManager;

private final UIEventListener uiEventListener;

public CdiVaadinServiceDelegate(VaadinService vaadinService,
BeanManager beanManager) {
this.beanManager = beanManager;
this.vaadinService = vaadinService;

uiEventListener = new UIEventListener(this);
}

public void init() throws ServiceException {
public void init(VaadinService vaadinService) throws ServiceException {
lookup(SystemMessagesProvider.class)
.ifPresent(vaadinService::setSystemMessagesProvider);
vaadinService.addUIInitListener(e -> getBeanManager().fireEvent(e));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ String getUIId() {

}

static class NavigationData {
static class NavigationData implements Serializable {
private final Class<?> navigationTarget;
private final List<Class<? extends RouterLayout>> layouts;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,39 +16,48 @@

package com.vaadin.cdi;

import com.vaadin.cdi.annotation.VaadinServiceEnabled;
import com.vaadin.cdi.annotation.VaadinServiceScoped;
import com.vaadin.cdi.context.ServiceUnderTestContext;
import com.vaadin.flow.di.Instantiator;
import com.vaadin.flow.server.CustomizedSystemMessages;
import com.vaadin.flow.server.DefaultSystemMessagesProvider;
import com.vaadin.flow.server.ServiceException;
import com.vaadin.flow.server.SystemMessages;
import com.vaadin.flow.server.SystemMessagesInfo;
import com.vaadin.flow.server.SystemMessagesProvider;

import org.apache.deltaspike.testcontrol.api.junit.CdiTestRunner;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;

import javax.enterprise.context.spi.Context;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.AmbiguousResolutionException;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;

import org.apache.deltaspike.testcontrol.api.junit.CdiTestRunner;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;

import com.vaadin.cdi.annotation.VaadinServiceEnabled;
import com.vaadin.cdi.annotation.VaadinServiceScoped;
import com.vaadin.cdi.context.ServiceUnderTestContext;
import com.vaadin.flow.component.ComponentUtil;
import com.vaadin.flow.component.PollEvent;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.di.Instantiator;
import com.vaadin.flow.server.CustomizedSystemMessages;
import com.vaadin.flow.server.DefaultSystemMessagesProvider;
import com.vaadin.flow.server.ServiceException;
import com.vaadin.flow.server.SystemMessages;
import com.vaadin.flow.server.SystemMessagesInfo;
import com.vaadin.flow.server.SystemMessagesProvider;
import com.vaadin.flow.server.VaadinSession;

import static com.vaadin.cdi.SerializationUtils.serializeAndDeserialize;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.any;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.same;
Expand All @@ -72,6 +81,15 @@ public SystemMessages getSystemMessages(

}

@Singleton
public static class UIListenerEventReceiver {

private UI pollEventUI;
void onPollEvent(@Observes PollEvent pollEvent) {
pollEventUI = pollEvent.getSource();
}
}

@Inject
private BeanManager beanManager;

Expand Down Expand Up @@ -182,6 +200,25 @@ public void loadInstantiators_serviceInitialized_instantiatorInstanceCreated()
assertEquals(mockInstantiator, maybeInstantiator.get());
}

@Test
public void fireUIInitListeners_serialization_UIserializableAndListenersWork() throws Exception {
initService(beanManager);

UIListenerEventReceiver uiListenerEventReceiver = service.getInstantiator().getOrCreate(UIListenerEventReceiver.class);
UI ui = new UI();
ui.getInternals().setSession(Mockito.mock(VaadinSession.class, Mockito.withSettings().serializable()));
service.fireUIInitListeners(ui);

ComponentUtil.fireEvent(ui, new PollEvent(ui, false));
assertEquals(ui, uiListenerEventReceiver.pollEventUI);

UI ui2 = serializeAndDeserialize(ui);
assertNotNull(ui2);

ComponentUtil.fireEvent(ui2, new PollEvent(ui2, false));
assertEquals(ui2, uiListenerEventReceiver.pollEventUI);
}

private void initService(BeanManager beanManager) throws ServiceException {
ServiceUnderTestContext serviceUnderTestContext = new ServiceUnderTestContext(beanManager);
serviceUnderTestContext.activate();
Expand Down
44 changes: 44 additions & 0 deletions vaadin-cdi/src/test/java/com/vaadin/cdi/SerializationUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright 2000-2023 Vaadin Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.vaadin.cdi;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public final class SerializationUtils {

private SerializationUtils() {
}

@SuppressWarnings("unchecked")
public static <S extends Serializable> S serializeAndDeserialize(S obj)
throws Exception {
// Serialize and deserialize
ByteArrayOutputStream bs = new ByteArrayOutputStream();
try (ObjectOutputStream out = new ObjectOutputStream(bs)) {
out.writeObject(obj);
}
byte[] data = bs.toByteArray();
try (ObjectInputStream in = new ObjectInputStream(
new ByteArrayInputStream(data))) {
return (S) in.readObject();
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,34 @@

package com.vaadin.cdi.context;

import java.io.Serializable;
import java.util.Collections;

import org.apache.deltaspike.core.api.provider.BeanProvider;
import org.apache.deltaspike.testcontrol.api.junit.CdiTestRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentMatchers;
import org.mockito.MockedStatic;
import org.mockito.Mockito;

import com.vaadin.cdi.annotation.NormalRouteScoped;
import com.vaadin.cdi.context.RouteScopedContext.NavigationData;
import com.vaadin.flow.component.ComponentUtil;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.startup.ApplicationConfiguration;

import static com.vaadin.cdi.SerializationUtils.serializeAndDeserialize;
import static org.junit.Assert.assertNotNull;

@RunWith(CdiTestRunner.class)
public class RouteContextNormalTest extends
AbstractContextTest<RouteContextNormalTest.RouteScopedTestBean> {

@NormalRouteScoped
@Route("")
public static class RouteScopedTestBean extends TestBean {
public static class RouteScopedTestBean extends TestBean implements Serializable {
}

@Override
Expand Down Expand Up @@ -63,4 +74,18 @@ protected boolean isNormalScoped() {
return true;
}

@Test
public void activeContext_UISerializable() throws Exception {
UIUnderTestContext context = (UIUnderTestContext) createContext();
context.activate();
BeanProvider.getContextualReference(getBeanType());
UI ui = context.getUi();
try (MockedStatic<ApplicationConfiguration> appCfg = Mockito.mockStatic(ApplicationConfiguration.class)) {
appCfg.when(() -> ApplicationConfiguration.get(ArgumentMatchers.any()))
.thenReturn(Mockito.mock(ApplicationConfiguration.class));
UI ui2 = serializeAndDeserialize(ui);
assertNotNull(ui2);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,26 @@

package com.vaadin.cdi.context;

import java.io.Serializable;
import java.util.Collections;

import org.apache.deltaspike.core.api.provider.BeanProvider;
import org.apache.deltaspike.testcontrol.api.junit.CdiTestRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentMatchers;
import org.mockito.MockedStatic;
import org.mockito.Mockito;

import com.vaadin.cdi.annotation.RouteScoped;
import com.vaadin.cdi.context.RouteScopedContext.NavigationData;
import com.vaadin.flow.component.ComponentUtil;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.startup.ApplicationConfiguration;

import static com.vaadin.cdi.SerializationUtils.serializeAndDeserialize;
import static org.junit.Assert.assertNotNull;

@RunWith(CdiTestRunner.class)
public class RouteContextPseudoTest extends
Expand All @@ -38,7 +49,7 @@ public void setUp() {

@RouteScoped
@Route("")
public static class RouteScopedTestBean extends TestBean {
public static class RouteScopedTestBean extends TestBean implements Serializable {
}

@Override
Expand Down Expand Up @@ -69,4 +80,18 @@ protected boolean isNormalScoped() {
return false;
}

@Test
public void activeContext_UISerializable() throws Exception {
UIUnderTestContext context = (UIUnderTestContext) createContext();
context.activate();
BeanProvider.getContextualReference(getBeanType());
UI ui = context.getUi();
try (MockedStatic<ApplicationConfiguration> appCfg = Mockito.mockStatic(ApplicationConfiguration.class)) {
appCfg.when(() -> ApplicationConfiguration.get(ArgumentMatchers.any()))
.thenReturn(Mockito.mock(ApplicationConfiguration.class));
UI ui2 = serializeAndDeserialize(ui);
assertNotNull(ui2);
}
}

}