Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*-
* #%L
* Json Migration Helper
* %%
* Copyright (C) 2025 Flowing Code
* %%
* 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.
* #L%
*/
package com.flowingcode.vaadin.jsonmigration;
/*
* Copyright 2000-2025 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.
*/

import com.vaadin.flow.component.page.PendingJavaScriptResult;
import com.vaadin.flow.function.SerializableConsumer;
import elemental.json.JsonValue;
import java.io.Serializable;

/**
* A pending result from a JavaScript snippet sent to the browser for evaluation. This interface
* utilizes Elemental JSON in order to abstract away breaking changes introduced in Vaadin version
* 25.
*
* @see PendingJavaScriptResult
* @author Vaadin Ltd
*/
public interface ElementalPendingJavaScriptResult extends Serializable {

/**
* Adds an untyped handler that will be run for a successful execution and a
* handler that will be run for a failed execution. One of the handlers will
* be invoked asynchronously when the result of the execution is sent back
* to the server. It is not possible to synchronously wait for the result of
* the execution while holding the session lock since the request handling
* thread that makes the result available will also need to lock the
* session.
* <p>
* Handlers can only be added before the execution has been sent to the
* browser.
*
* @param resultHandler
* a handler for the JSON representation of the value from a
* successful execution, not <code>null</code>
* @param errorHandler
* a handler for an error message in case the execution failed,
* or <code>null</code> to ignore errors
*/
void then(SerializableConsumer<JsonValue> resultHandler,
SerializableConsumer<String> errorHandler);

/**
* Adds an untyped handler that will be run for a successful execution. The
* handler will be invoked asynchronously if the execution was successful.
* In case of a failure, no handler will be run.
* <p>
* A handler can only be added before the execution has been sent to the
* browser.
*
* @param resultHandler
* a handler for the JSON representation of the return value from
* a successful execution, not <code>null</code>
*/
default void then(SerializableConsumer<JsonValue> resultHandler) {
then(resultHandler, null);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@
*/
package com.flowingcode.vaadin.jsonmigration;

import com.vaadin.flow.component.page.PendingJavaScriptResult;
import com.vaadin.flow.dom.DomEvent;
import com.vaadin.flow.dom.Element;
import com.vaadin.flow.server.Version;
import elemental.json.JsonObject;
import elemental.json.JsonValue;
import java.io.Serializable;
import java.lang.reflect.Method;
import lombok.SneakyThrows;

Expand Down Expand Up @@ -114,6 +116,22 @@ public static void setPropertyJson(Element element, String name, JsonValue json)
invoke(Element_setPropertyJson, element, name, json);
}

/**
* Asynchronously runs the given JavaScript expression in the browser in the context of this
* element.
*
* @param element the {@code Element} on which to run the JavaScript expression
* @param expression the JavaScript expression to invoke
* @param parameters parameters to pass to the expression
* @return a pending result that can be used to get a value returned from the expression
* @see Element#executeJs(String, Serializable...)
*/
public static ElementalPendingJavaScriptResult executeJs(Element element, String expression,
Serializable... parameters) {
PendingJavaScriptResult result = element.executeJs(expression, parameters);
return helper.convertPendingJavaScriptResult(result);
}

/**
* Gets additional data related to the event.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
*/
package com.flowingcode.vaadin.jsonmigration;

import com.vaadin.flow.component.page.PendingJavaScriptResult;
import elemental.json.JsonValue;

import java.lang.reflect.Method;
Expand All @@ -29,5 +30,7 @@ interface JsonMigrationHelper {
JsonValue convertToJsonValue(Object object);

Object invoke(Method method, Object instance, Object... args);


ElementalPendingJavaScriptResult convertPendingJavaScriptResult(PendingJavaScriptResult result);

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,13 @@

import java.lang.reflect.Method;
import java.util.Arrays;
import com.vaadin.flow.component.page.PendingJavaScriptResult;
import com.vaadin.flow.function.SerializableConsumer;
import elemental.json.Json;
import elemental.json.JsonArray;
import elemental.json.JsonObject;
import elemental.json.JsonValue;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.SneakyThrows;
import tools.jackson.databind.JsonNode;
Expand Down Expand Up @@ -135,4 +138,31 @@ private static BaseJsonNode convertToJsonNode(JsonValue jsonValue) {
}
}


@Override
public ElementalPendingJavaScriptResult convertPendingJavaScriptResult(
PendingJavaScriptResult result) {
return new PendingJavaScriptResultImpl(result);
}

@SuppressWarnings("serial")
@AllArgsConstructor
private static final class PendingJavaScriptResultImpl
implements ElementalPendingJavaScriptResult {
private final PendingJavaScriptResult delegate;

@SuppressWarnings("rawtypes")
private static SerializableConsumer wrap(SerializableConsumer<JsonValue> resultHandler) {
return (SerializableConsumer<JsonNode>) node -> resultHandler.accept(convertToJsonValue(node));
};

@Override
@SuppressWarnings("unchecked")
public void then(SerializableConsumer<JsonValue> resultHandler,
SerializableConsumer<String> errorHandler) {
delegate.then(wrap(resultHandler), errorHandler);
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@
*/
package com.flowingcode.vaadin.jsonmigration;

import com.vaadin.flow.component.page.PendingJavaScriptResult;
import java.lang.reflect.Method;
import elemental.json.JsonValue;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.SneakyThrows;
import lombok.experimental.Delegate;

@NoArgsConstructor
class LegacyJsonMigrationHelper implements JsonMigrationHelper {
Expand All @@ -43,4 +46,18 @@ public Object invoke(Method method, Object instance, Object... args) {
return method.invoke(instance, args);
}

@Override
public ElementalPendingJavaScriptResult convertPendingJavaScriptResult(
PendingJavaScriptResult result) {
return new PendingJavaScriptResultImpl(result);
}

@SuppressWarnings("serial")
@AllArgsConstructor
private static final class PendingJavaScriptResultImpl
implements ElementalPendingJavaScriptResult, PendingJavaScriptResult {
@Delegate
private final PendingJavaScriptResult delegate;
}

}