PL-9009 Using servlets defined in app components

This commit is contained in:
Daniil Tsarev 2018-01-24 10:22:45 +04:00
parent 4ee8317f1c
commit b26606926a
5 changed files with 236 additions and 0 deletions

View File

@ -19,6 +19,9 @@ package com.haulmont.cuba.core.sys;
import ch.qos.logback.classic.LoggerContext;
import com.google.common.base.Splitter;
import com.haulmont.cuba.core.global.Events;
import com.haulmont.cuba.core.sys.servlet.events.ServletContextDestroyedEvent;
import com.haulmont.cuba.core.sys.servlet.events.ServletContextInitializedEvent;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.text.StrSubstitutor;
@ -72,6 +75,11 @@ public abstract class AbstractWebAppContextLoader extends AbstractAppContextLoad
initAppContext();
afterInitAppContext();
ApplicationContext applicationContext = AppContext.getApplicationContext();
applicationContext.getBean(Events.class)
.publish(new ServletContextInitializedEvent(sc, applicationContext));
AppContext.Internals.startContext();
log.info("AppContext started");
} catch (RuntimeException e) {
@ -90,6 +98,14 @@ public abstract class AbstractWebAppContextLoader extends AbstractAppContextLoad
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
ApplicationContext applicationContext = AppContext.getApplicationContext();
applicationContext.getBean(Events.class)
.publish(new ServletContextDestroyedEvent(
servletContextEvent.getServletContext(),
applicationContext
));
AppContext.Internals.stopContext();
AppContext.Internals.setApplicationContext(null);

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2008-2018 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 com.haulmont.cuba.core.sys.servlet;
import org.springframework.context.ApplicationContext;
import javax.servlet.Filter;
import javax.servlet.Servlet;
/**
* A bean that enables to create Servlets and Filters with correct classloader to be able to use such static classes
* as {@link com.haulmont.cuba.core.sys.AppContext}.
* <p>
* It is recommended to use this bean to guarantee correct work for all deployment options.
*/
public interface ServletRegistrationManager {
String NAME = "cuba_ServletRegistrationManager";
/**
* Creates a servlet of the given {@code servletClass} with a classloader of the given {@code context}.
*
* @param context {@link ApplicationContext} instance
* @param servletClass Fully qualified name of the created servlet
* @return {@link Servlet} instance
*/
Servlet createServlet(ApplicationContext context, String servletClass);
/**
* Creates a filter of the given {@code filterClass} with a classloader of the given {@code context}.
*
* @param context {@link ApplicationContext} instance
* @param filterClass Fully qualified name of the created filter
* @return {@link Filter} instance
*/
Filter createFilter(ApplicationContext context, String filterClass);
}

View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2008-2018 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 com.haulmont.cuba.core.sys.servlet;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import javax.servlet.Filter;
import javax.servlet.Servlet;
@Component(ServletRegistrationManager.NAME)
public class ServletRegistrationManagerBean implements ServletRegistrationManager {
@Override
public Servlet createServlet(ApplicationContext context, String servletClass) {
Class<? extends Servlet> clazz;
try {
//noinspection unchecked
clazz = (Class<? extends Servlet>) context.getClassLoader()
.loadClass(servletClass);
} catch (ClassNotFoundException e) {
throw new RuntimeException("Failed to load servlet class: " + servletClass, e);
}
Servlet servlet;
try {
servlet = clazz.newInstance();
} catch (IllegalAccessException | InstantiationException e) {
throw new RuntimeException("Failed to get an instance of a class: " + servletClass, e);
}
return servlet;
}
@Override
public Filter createFilter(ApplicationContext context, String filterClass) {
Class<? extends Filter> clazz;
try {
//noinspection unchecked
clazz = (Class<? extends Filter>) context.getClassLoader()
.loadClass(filterClass);
} catch (ClassNotFoundException e) {
throw new RuntimeException("Failed to load filter class: " + filterClass, e);
}
Filter servlet;
try {
servlet = clazz.newInstance();
} catch (IllegalAccessException | InstantiationException e) {
throw new RuntimeException("Failed to get an instance of a class: " + filterClass, e);
}
return servlet;
}
}

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2008-2018 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 com.haulmont.cuba.core.sys.servlet.events;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent;
import javax.servlet.ServletContext;
/**
* Application lifecycle event.
* <p>
* Published when Servlet and Application are about to be shut down. Enables to free resources manually.
*/
public class ServletContextDestroyedEvent extends ApplicationEvent {
protected ApplicationContext applicationContext;
public ServletContextDestroyedEvent(ServletContext source, ApplicationContext applicationContext) {
this(source);
this.applicationContext = applicationContext;
}
public ServletContextDestroyedEvent(ServletContext source) {
super(source);
}
@Override
public ServletContext getSource() {
return (ServletContext) super.getSource();
}
public ApplicationContext getApplicationContext() {
return applicationContext;
}
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2008-2018 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 com.haulmont.cuba.core.sys.servlet.events;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent;
import javax.servlet.ServletContext;
/**
* Application lifecycle event.
* <p>
* Published right after initialization of Servlet and Application contexts. Enables to register custom
* {@code Servlets}, {@code Filters} and {@code Listeners} manually.
*/
public class ServletContextInitializedEvent extends ApplicationEvent {
protected ApplicationContext applicationContext;
public ServletContextInitializedEvent(ServletContext source, ApplicationContext applicationContext) {
this(source);
this.applicationContext = applicationContext;
}
public ServletContextInitializedEvent(ServletContext source) {
super(source);
}
@Override
public ServletContext getSource() {
return (ServletContext) super.getSource();
}
public ApplicationContext getApplicationContext() {
return applicationContext;
}
}