Skip to content

Commit

Permalink
Move Vaadin servlet from Studio jmix-framework#1554
Browse files Browse the repository at this point in the history
  • Loading branch information
Mikhail Fedoseev committed Apr 14, 2023
1 parent 6074335 commit 142cd7d
Show file tree
Hide file tree
Showing 15 changed files with 1,157 additions and 63 deletions.
32 changes: 17 additions & 15 deletions jmix-flowui/flowui-devserver/flowui-devserver.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,30 +14,32 @@
* limitations under the License.
*/

plugins {
id 'com.github.johnrengelman.shadow' version '8.1.1'
}

apply plugin: 'java'
apply plugin: 'groovy'
apply plugin: 'io.jmix'

apply plugin: 'maven-publish'

group = 'io.jmix.flowui'
archivesBaseName = 'jmix-flowui-devserver'

configurations {
extraLibs
}

dependencies {
//extraLibs(project(':flowui-kit'))
api(project(":flowui-kit"))

extraLibs("com.vaadin:flow-server:$vaadinFlowVersion")
extraLibs("javax.servlet:javax.servlet-api:4.0.1")
api("org.eclipse.jetty:jetty-continuation:$jettyVersion")
api("org.eclipse.jetty:jetty-webapp:$jettyVersion")
api("org.eclipse.jetty.websocket:websocket-server:$jettyVersion")
api("org.eclipse.jetty.websocket:javax-websocket-server-impl:$jettyVersion")

implementation("com.vaadin:flow-server:$vaadinFlowVersion")
implementation("javax.servlet:javax.servlet-api:4.0.1")
api('org.slf4j:slf4j-nop:2.0.7')
api("javax.servlet:javax.servlet-api:4.0.1")
}

jar {
duplicatesStrategy = DuplicatesStrategy.WARN
from {
configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) }
}
shadowJar {
dependsOn(jar)
mergeServiceFiles()
archiveClassifier.set("")
}
3 changes: 2 additions & 1 deletion jmix-flowui/flowui-devserver/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@
# limitations under the License.
#

vaadinFlowVersion=23.3.0
vaadinFlowVersion=23.3.0
jettyVersion=9.4.45.v20220203
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* Copyright 2022 Haulmont.
*
* 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 io.jmix.flowui.devserver;

import com.vaadin.flow.server.startup.ServletContextListeners;
import io.jmix.flowui.devserver.servlet.JmixErrorHandler;
import io.jmix.flowui.devserver.servlet.JmixServletContextListener;
import io.jmix.flowui.devserver.servlet.JmixSystemPropertiesLifeCycleListener;
import io.jmix.flowui.devserver.servlet.JmixVaadinServlet;
import org.eclipse.jetty.annotations.AnnotationConfiguration;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.server.handler.ShutdownHandler;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.JettyWebXmlConfiguration;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;

import javax.servlet.ServletException;
import java.util.Collections;
import java.util.Map;
import java.util.Properties;

/**
* Used in Studio.
*/
@SuppressWarnings("unused")
public class FlowJettyServer extends Server {

private final Map<String, Object> params;

public FlowJettyServer(int port, Map<String, Object> params) {
super(port);
this.params = params;
}

public void initAndStart() throws Exception {
init();
start();
}

private void init() throws ServletException {
WebAppContext context = createContext();
this.setHandler(
new HandlerList(
context,
new ShutdownHandler("studio")
)
);
this.addLifeCycleListener(
new JmixSystemPropertiesLifeCycleListener(
(String) params.get("ProjectBaseDir"),
(String) params.get("IsPnpmEnabled"),
(Properties) params.get("Properties")
)
);
Configuration.ClassList
.setServerDefault(this)
.addBefore(
JettyWebXmlConfiguration.class.getName(),
AnnotationConfiguration.class.getName()
);
}

private WebAppContext createContext() throws ServletException {
WebAppContext context = new WebAppContext();
context.setContextPath("/");
context.setClassLoader(FlowJettyServer.class.getClassLoader());
context.setExtraClasspath((String) params.get("ExtraClassPath"));
context.setResourceBase((String) params.get("ResourceBaseDir"));
context.addServlet(JmixVaadinServlet.class, "/*");
context.setConfigurationDiscovered(true);
context.getServletContext().setExtendedListenerTypes(true);
context.addEventListener(new ServletContextListeners());
WebSocketServerContainerInitializer.initialize(context);
context.setErrorHandler(new JmixErrorHandler());
context.addEventListener(new JmixServletContextListener(params));
return context;
}

private FlowJettyServer() {
this.params = Collections.emptyMap();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,13 @@ public class FrontendUtils {
public static final String PARAM_THEME_CLASS = "vaadin.frontend.theme.class";
public static final String PARAM_STUDIO_DIR = "vaadin.frontend.studio.folder";

public static final String VIEW_DESIGNER_FOLDER = "/.jmix/screen-designer";
public static final String FRONTEND_FOLDER = VIEW_DESIGNER_FOLDER + "/frontend";
public static final String BUILD_FOLDER = VIEW_DESIGNER_FOLDER + "/build";
public static final String BUILD_FRONTEND_FOLDER = BUILD_FOLDER + "/frontend";
public static final String FLOW_FRONTEND_FOLDER = BUILD_FOLDER + "/flow-frontend";
public static final String GENERATED_FRONTEND_FOLDER = FRONTEND_FOLDER + "/generated";

/**
* Set to {@code true} to ignore node/npm tool version checks.
*/
Expand Down Expand Up @@ -1233,12 +1240,21 @@ public static FrontendVersion getPackageVersionFromJson(
* @param format Format of the line to send to console, it must contain a `%s`
* outlet for the message
* @param message the string to show
*
* @see FrontendUtils#console(String, Object, boolean)
*/
@SuppressWarnings("squid:S106")
public static void console(String format, Object message) {
console(format, message, true);
}

/**
* @see FrontendUtils#console(String, Object)
*/
public static void console(Object message) {
console(FrontendUtils.RED, message, true);
}

public static void console(String format, Object message, boolean logInFile) {
System.out.printf(format, message);
if (logInFile) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright 2022 Haulmont.
*
* 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 io.jmix.flowui.devserver.servlet;

import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.ErrorHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.Writer;

public class JmixErrorHandler extends ErrorHandler {
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
super.handle(target, baseRequest, request, response);
}

@Override
protected void handleErrorPage(HttpServletRequest request, Writer writer, int code, String message) throws IOException {
super.handleErrorPage(request, writer, code, message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* Copyright 2022 Haulmont.
*
* 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 io.jmix.flowui.devserver.servlet;

import com.vaadin.flow.component.PushConfiguration;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.page.Push;
import com.vaadin.flow.server.AppShellRegistry;
import com.vaadin.flow.server.VaadinRequest;
import com.vaadin.flow.server.VaadinResponse;
import com.vaadin.flow.server.VaadinSession;
import com.vaadin.flow.server.communication.JavaScriptBootstrapHandler;
import com.vaadin.flow.shared.communication.PushMode;
import elemental.json.JsonObject;

import java.util.Optional;

public class JmixJavaScriptBootstrapHandler extends JavaScriptBootstrapHandler {

public JmixJavaScriptBootstrapHandler() {
super();
}

@Override
protected BootstrapContext createAndInitUI(Class<? extends UI> uiClass,
VaadinRequest request,
VaadinResponse response,
VaadinSession session) {
UI ui = new JmixJavaScriptBootstrapUI();
ui.getInternals().setContextRoot(request.getService().getContextRootRelativePath(request));

PushConfiguration pushConfiguration = ui.getPushConfiguration();

ui.getInternals().setSession(session);
ui.setLocale(session.getLocale());

BootstrapContext context = createBootstrapContext(
request,
response,
ui,
vaadinRequest -> vaadinRequest.getService().getContextRootRelativePath(request)
);


Optional<Push> push = context.getPageConfigurationAnnotation(Push.class);

setupPushConnectionFactory(pushConfiguration, context);
pushConfiguration.setPushMode
(PushMode.MANUAL);
push.stream()
.map(Push::transport)
.forEach(pushConfiguration::setTransport);

// Set thread local here so it is available in init
UI.setCurrent(ui);
ui.doInit(request, session.getNextUIid(), context.getAppId());
session.addUI(ui);

// After init and adding UI to session fire init listeners.
session.getService().fireUIInitListeners(ui);

initializeUIWithRouter(context, ui);

JsonObject config = context.getApplicationParameters();

String requestURL = getRequestUrl(request);

AppShellRegistry registry = AppShellRegistry.getInstance(session.getService().getContext());
registry.modifyPushConfiguration(pushConfiguration);

config.put("requestURL", requestURL);

return context;
}
}
Loading

0 comments on commit 142cd7d

Please sign in to comment.