Merge pull request #88 from rmpestano/native
Quarkus native mode support
diff --git a/README.md b/README.md
index 9516fc8..9605bf4 100644
--- a/README.md
+++ b/README.md
@@ -70,7 +70,7 @@
## Quarkus extension
Since 2.3-next a Quarkus extension is available. A sample project can be found here: https://github.com/apache/myfaces/blob/master/extensions/quarkus/showcase/
-Native mode is currently not supported as EL makes extensive use of reflection.
+
### Differences to a normal servlet container
- You need to put your views under src/main/resources/META-INF/resources as Quarkus doesn't create a WAR and src/main/webapp is ignored!
diff --git a/extensions/quarkus/deployment/src/main/java/org/apache/myfaces/core/extensions/quarkus/deployment/MyFacesProcessor.java b/extensions/quarkus/deployment/src/main/java/org/apache/myfaces/core/extensions/quarkus/deployment/MyFacesProcessor.java
index e1cff19..6cf6775 100644
--- a/extensions/quarkus/deployment/src/main/java/org/apache/myfaces/core/extensions/quarkus/deployment/MyFacesProcessor.java
+++ b/extensions/quarkus/deployment/src/main/java/org/apache/myfaces/core/extensions/quarkus/deployment/MyFacesProcessor.java
@@ -1,607 +1,613 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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 org.apache.myfaces.core.extensions.quarkus.deployment;
-
-import com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl;
-import com.sun.org.apache.xpath.internal.functions.FuncLocalPart;
-import com.sun.org.apache.xpath.internal.functions.FuncNot;
-import java.io.IOException;
-import java.util.Optional;
-
-import javax.faces.application.ProjectStage;
-import javax.faces.application.StateManager;
-import javax.faces.application.ViewHandler;
-import javax.faces.component.FacesComponent;
-import javax.faces.component.behavior.FacesBehavior;
-import javax.faces.convert.FacesConverter;
-import javax.faces.flow.FlowScoped;
-import javax.faces.flow.builder.FlowDefinition;
-import javax.faces.model.FacesDataModel;
-import javax.faces.push.PushContext;
-import javax.faces.render.FacesBehaviorRenderer;
-import javax.faces.render.FacesRenderer;
-import javax.faces.validator.FacesValidator;
-import javax.faces.view.ViewScoped;
-import javax.faces.view.facelets.FaceletsResourceResolver;
-import javax.faces.webapp.FacesServlet;
-
-import org.apache.myfaces.cdi.FacesScoped;
-import org.apache.myfaces.cdi.JsfApplicationArtifactHolder;
-import org.apache.myfaces.cdi.JsfArtifactProducer;
-import org.apache.myfaces.cdi.config.FacesConfigBeanHolder;
-import org.apache.myfaces.cdi.model.FacesDataModelManager;
-import org.apache.myfaces.cdi.view.ViewScopeBeanHolder;
-import org.apache.myfaces.cdi.view.ViewTransientScoped;
-import org.apache.myfaces.config.MyfacesConfig;
-import org.apache.myfaces.config.annotation.CdiAnnotationProviderExtension;
-import org.apache.myfaces.config.element.NamedEvent;
-import org.apache.myfaces.flow.cdi.FlowBuilderFactoryBean;
-import org.apache.myfaces.flow.cdi.FlowScopeBeanHolder;
-import org.apache.myfaces.push.cdi.PushContextFactoryBean;
-import org.apache.myfaces.push.cdi.WebsocketApplicationBean;
-import org.apache.myfaces.push.cdi.WebsocketChannelTokenBuilderBean;
-import org.apache.myfaces.push.cdi.WebsocketSessionBean;
-import org.apache.myfaces.push.cdi.WebsocketViewBean;
-import org.apache.myfaces.webapp.StartupServletContextListener;
-import org.eclipse.microprofile.config.Config;
-import org.eclipse.microprofile.config.ConfigProvider;
-import org.jboss.jandex.AnnotationInstance;
-import org.jboss.jandex.AnnotationValue;
-import org.jboss.jandex.DotName;
-
-import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
-import io.quarkus.arc.deployment.BeanDefiningAnnotationBuildItem;
-import io.quarkus.arc.deployment.BeanRegistrarBuildItem;
-import io.quarkus.arc.deployment.BeanRegistrationPhaseBuildItem;
-import io.quarkus.arc.deployment.ContextRegistrarBuildItem;
-import io.quarkus.arc.processor.ContextRegistrar;
-import io.quarkus.deployment.annotations.BuildProducer;
-import io.quarkus.deployment.annotations.BuildStep;
-import io.quarkus.deployment.annotations.ExecutionTime;
-import io.quarkus.deployment.annotations.Record;
-import io.quarkus.deployment.builditem.AdditionalApplicationArchiveMarkerBuildItem;
-import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
-import io.quarkus.deployment.builditem.FeatureBuildItem;
-import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem;
-import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBundleBuildItem;
-import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
-import org.apache.myfaces.core.extensions.quarkus.runtime.MyFacesRecorder;
-import org.apache.myfaces.core.extensions.quarkus.runtime.QuarkusFacesInitilializer;
-import org.apache.myfaces.core.extensions.quarkus.runtime.scopes.QuarkusFacesScopeContext;
-import org.apache.myfaces.core.extensions.quarkus.runtime.scopes.QuarkusFlowScopedContext;
-import org.apache.myfaces.core.extensions.quarkus.runtime.scopes.QuarkusViewScopeContext;
-import org.apache.myfaces.core.extensions.quarkus.runtime.scopes.QuarkusViewTransientScopeContext;
-import org.apache.myfaces.core.extensions.quarkus.runtime.spi.QuarkusInjectionProvider;
-import io.quarkus.runtime.LaunchMode;
-import io.quarkus.runtime.configuration.ProfileManager;
-import io.quarkus.undertow.deployment.ListenerBuildItem;
-import io.quarkus.undertow.deployment.ServletBuildItem;
-import io.quarkus.undertow.deployment.ServletInitParamBuildItem;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-import javax.el.ELResolver;
-import javax.faces.FactoryFinder;
-import javax.faces.application.Application;
-import javax.faces.component.UIComponent;
-import javax.faces.component.behavior.Behavior;
-import javax.faces.context.FacesContext;
-import javax.faces.convert.Converter;
-import javax.faces.event.ExceptionQueuedEventContext;
-import javax.faces.event.SystemEvent;
-import javax.faces.render.ClientBehaviorRenderer;
-import javax.faces.render.Renderer;
-import javax.faces.validator.Validator;
-import javax.faces.view.facelets.ComponentHandler;
-import javax.faces.view.facelets.ConverterHandler;
-import javax.faces.view.facelets.MetaRuleset;
-import javax.faces.view.facelets.TagHandler;
-import javax.faces.view.facelets.ValidatorHandler;
-import org.apache.myfaces.application.viewstate.StateUtils;
-import org.apache.myfaces.cdi.util.BeanEntry;
-import org.apache.myfaces.config.FacesConfigurator;
-import org.apache.myfaces.core.extensions.quarkus.runtime.spi.QuarkusFactoryFinderProvider;
-import org.apache.myfaces.el.ELResolverBuilderForFaces;
-import org.apache.myfaces.lifecycle.RestoreViewSupport;
-import org.apache.myfaces.renderkit.ErrorPageWriter;
-import org.apache.myfaces.spi.FactoryFinderProviderFactory;
-import org.apache.myfaces.spi.impl.DefaultWebConfigProviderFactory;
-import org.apache.myfaces.util.ExternalContextUtils;
-import org.apache.myfaces.util.lang.ClassUtils;
-import org.apache.myfaces.view.ViewScopeProxyMap;
-import org.apache.myfaces.view.facelets.compiler.SAXCompiler;
-import org.apache.myfaces.view.facelets.compiler.TagLibraryConfig;
-import org.apache.myfaces.view.facelets.tag.MethodRule;
-import org.apache.myfaces.view.facelets.tag.jsf.ComponentSupport;
-import org.apache.myfaces.webapp.AbstractFacesInitializer;
-import org.apache.myfaces.webapp.FaceletsInitilializer;
-import org.apache.myfaces.webapp.MyFacesContainerInitializer;
-import org.jboss.jandex.ClassInfo;
-
-class MyFacesProcessor
-{
-
- private static final Class[] BEAN_CLASSES =
- {
- JsfApplicationArtifactHolder.class,
-
- JsfArtifactProducer.class,
-
- FacesConfigBeanHolder.class,
-
- FacesDataModelManager.class,
-
- ViewScopeBeanHolder.class,
-
- CdiAnnotationProviderExtension.class,
-
- PushContextFactoryBean.class,
- WebsocketChannelTokenBuilderBean.class,
- WebsocketSessionBean.class,
- WebsocketViewBean.class,
- WebsocketApplicationBean.class,
-
- FlowBuilderFactoryBean.class,
- FlowScopeBeanHolder.class
- };
-
- private static final String[] BEAN_DEFINING_ANNOTATION_CLASSES =
- {
- FacesComponent.class.getName(),
- FacesBehavior.class.getName(),
- FacesConverter.class.getName(),
- FacesValidator.class.getName(),
- FacesRenderer.class.getName(),
- NamedEvent.class.getName(),
- FacesBehaviorRenderer.class.getName(),
- FaceletsResourceResolver.class.getName(),
- FlowDefinition.class.getName()
- };
-
- private static final String[] FACTORIES =
- {
- FactoryFinder.APPLICATION_FACTORY,
- FactoryFinder.EXCEPTION_HANDLER_FACTORY,
- FactoryFinder.EXTERNAL_CONTEXT_FACTORY,
- FactoryFinder.FACES_CONTEXT_FACTORY,
- FactoryFinder.LIFECYCLE_FACTORY,
- FactoryFinder.PARTIAL_VIEW_CONTEXT_FACTORY,
- FactoryFinder.RENDER_KIT_FACTORY,
- FactoryFinder.TAG_HANDLER_DELEGATE_FACTORY,
- FactoryFinder.VIEW_DECLARATION_LANGUAGE_FACTORY,
- FactoryFinder.VISIT_CONTEXT_FACTORY,
- FactoryFinder.FACELET_CACHE_FACTORY,
- FactoryFinder.FLASH_FACTORY,
- FactoryFinder.FLOW_HANDLER_FACTORY,
- FactoryFinder.CLIENT_WINDOW_FACTORY,
- FactoryFinder.SEARCH_EXPRESSION_CONTEXT_FACTORY
- };
-
- @BuildStep
- void buildFeature(BuildProducer<FeatureBuildItem> feature) throws IOException
- {
- feature.produce(new FeatureBuildItem("myfaces"));
- }
-
- @BuildStep
- void buildServlet(BuildProducer<FeatureBuildItem> feature,
- BuildProducer<ServletBuildItem> servlet,
- BuildProducer<ListenerBuildItem> listener) throws IOException
- {
- servlet.produce(ServletBuildItem.builder("Faces Servlet", FacesServlet.class.getName())
- .addMapping("*.xhtml")
- .build());
-
- // sometimes Quarkus doesn't scan web-fragments?! lets add it manually
- listener.produce(new ListenerBuildItem(StartupServletContextListener.class.getName()));
- }
-
- @BuildStep
- void buildCdiBeans(BuildProducer<AdditionalBeanBuildItem> additionalBean,
- BuildProducer<BeanDefiningAnnotationBuildItem> beanDefiningAnnotation) throws IOException
- {
- for (Class<?> clazz : BEAN_CLASSES)
- {
- additionalBean.produce(AdditionalBeanBuildItem.unremovableOf(clazz));
- }
-
- for (String clazz : BEAN_DEFINING_ANNOTATION_CLASSES)
- {
- beanDefiningAnnotation.produce(new BeanDefiningAnnotationBuildItem(DotName.createSimple(clazz)));
- }
-
- }
-
- @BuildStep
- void buildCdiScopes(BuildProducer<ContextRegistrarBuildItem> contextRegistrar) throws IOException
- {
- contextRegistrar.produce(new ContextRegistrarBuildItem(new ContextRegistrar()
- {
- @Override
- public void register(ContextRegistrar.RegistrationContext registrationContext)
- {
- registrationContext.configure(ViewScoped.class)
- .normal()
- .contextClass(QuarkusViewScopeContext.class)
- .done();
- registrationContext.configure(FacesScoped.class)
- .normal()
- .contextClass(QuarkusFacesScopeContext.class)
- .done();
- registrationContext.configure(ViewTransientScoped.class)
- .normal()
- .contextClass(QuarkusViewTransientScopeContext.class)
- .done();
- registrationContext.configure(FlowScoped.class)
- .normal()
- .contextClass(QuarkusFlowScopedContext.class)
- .done();
- }
- }));
- }
-
- @BuildStep
- void buildInitParams(BuildProducer<ServletInitParamBuildItem> initParam) throws IOException
- {
- initParam.produce(new ServletInitParamBuildItem(
- MyfacesConfig.INJECTION_PROVIDER, QuarkusInjectionProvider.class.getName()));
- initParam.produce(new ServletInitParamBuildItem(
- MyfacesConfig.FACES_INITIALIZER, QuarkusFacesInitilializer.class.getName()));
- initParam.produce(new ServletInitParamBuildItem(
- MyfacesConfig.SUPPORT_JSP, "false"));
- }
-
- @BuildStep
- void buildRecommendedInitParams(BuildProducer<ServletInitParamBuildItem> initParam) throws IOException
- {
- // user config
- Config config = ConfigProvider.getConfig();
-
- Optional<String> projectStage = resolveProjectStage(config);
- initParam.produce(new ServletInitParamBuildItem(ProjectStage.PROJECT_STAGE_PARAM_NAME, projectStage.get()));
-
- Optional<String> enableWebsocketsEndpoint = config.getOptionalValue(
- PushContext.ENABLE_WEBSOCKET_ENDPOINT_PARAM_NAME,
- String.class);
- if (enableWebsocketsEndpoint.isPresent())
- {
- initParam.produce(new ServletInitParamBuildItem(PushContext.ENABLE_WEBSOCKET_ENDPOINT_PARAM_NAME,
- enableWebsocketsEndpoint.get()));
- }
-
- // common
- initParam.produce(new ServletInitParamBuildItem(
- MyfacesConfig.LOG_WEB_CONTEXT_PARAMS, "false"));
- initParam.produce(new ServletInitParamBuildItem(
- StateManager.STATE_SAVING_METHOD_PARAM_NAME, StateManager.STATE_SAVING_METHOD_SERVER));
- initParam.produce(new ServletInitParamBuildItem(
- StateManager.SERIALIZE_SERVER_STATE_PARAM_NAME, "false"));
-
- // perf
- initParam.produce(new ServletInitParamBuildItem(
- MyfacesConfig.CHECK_ID_PRODUCTION_MODE, "false"));
- initParam.produce(new ServletInitParamBuildItem(
- MyfacesConfig.EARLY_FLUSH_ENABLED, "true"));
- initParam.produce(new ServletInitParamBuildItem(
- MyfacesConfig.CACHE_EL_EXPRESSIONS, "alwaysRecompile"));
- initParam.produce(new ServletInitParamBuildItem(
- MyfacesConfig.COMPRESS_STATE_IN_SESSION, "false"));
- initParam.produce(new ServletInitParamBuildItem(
- MyfacesConfig.NUMBER_OF_VIEWS_IN_SESSION, "15"));
- initParam.produce(new ServletInitParamBuildItem(
- MyfacesConfig.NUMBER_OF_SEQUENTIAL_VIEWS_IN_SESSION, "3"));
-
- // MyFaces uses default 0, which means always recompile
- if (ProjectStage.valueOf(projectStage.get()) == ProjectStage.Development)
- {
- initParam.produce(new ServletInitParamBuildItem(
- ViewHandler.FACELETS_REFRESH_PERIOD_PARAM_NAME, "1"));
- }
-
- // primefaces perf
- initParam.produce(new ServletInitParamBuildItem(
- "primefaces.SUBMIT", "partial"));
- initParam.produce(new ServletInitParamBuildItem(
- "primefaces.MOVE_SCRIPTS_TO_BOTTOM", "true"));
- }
-
- @BuildStep
- @Record(ExecutionTime.STATIC_INIT)
- void buildAnnotationProviderIntegration(MyFacesRecorder recorder, CombinedIndexBuildItem combinedIndex)
- throws IOException
- {
- for (String clazz : BEAN_DEFINING_ANNOTATION_CLASSES)
- {
- combinedIndex.getIndex()
- .getAnnotations(DotName.createSimple(clazz))
- .stream()
- .forEach(annotation -> recorder.registerAnnotatedClass(annotation.name().toString(),
- annotation.target().asClass().name().toString()));
- }
- }
-
- private Optional<String> resolveProjectStage(Config config)
- {
- Optional<String> projectStage = config.getOptionalValue(ProjectStage.PROJECT_STAGE_PARAM_NAME,
- String.class);
- if (!projectStage.isPresent())
- {
- projectStage = Optional.of(ProjectStage.Production.name());
- if (LaunchMode.DEVELOPMENT.getDefaultProfile().equals(ProfileManager.getActiveProfile()))
- {
- projectStage = Optional.of(ProjectStage.Development.name());
- }
- else if (LaunchMode.TEST.getDefaultProfile().equals(ProfileManager.getActiveProfile()))
- {
- projectStage = Optional.of(ProjectStage.SystemTest.name());
- }
- }
- return projectStage;
- }
-
- @BuildStep
- void buildMangedPropertyProducers(BeanRegistrationPhaseBuildItem beanRegistrationPhase,
- BuildProducer<BeanRegistrationPhaseBuildItem.BeanConfiguratorBuildItem> beanConfigurators)
- throws IOException
- {
- ManagedPropertyBuildStep.build(beanRegistrationPhase, beanConfigurators);
- }
-
- @BuildStep
- @Record(ExecutionTime.STATIC_INIT)
- void buildFacesDataModels(MyFacesRecorder recorder,
- BuildProducer<BeanRegistrarBuildItem> beanConfigurators,
- CombinedIndexBuildItem combinedIndex) throws IOException
- {
- for (AnnotationInstance ai : combinedIndex.getIndex()
- .getAnnotations(DotName.createSimple(FacesDataModel.class.getName())))
- {
- AnnotationValue forClass = ai.value("forClass");
- if (forClass != null)
- {
- recorder.registerFacesDataModel(
- ai.target().asClass().name().toString(),
- forClass.asClass().name().toString());
- }
- }
- }
-
- @BuildStep
- @Record(ExecutionTime.STATIC_INIT)
- void buildFlowScopedMapping(MyFacesRecorder recorder,
- CombinedIndexBuildItem combinedIndex) throws IOException
- {
- for (AnnotationInstance ai : combinedIndex.getIndex()
- .getAnnotations(DotName.createSimple(FlowScoped.class.getName())))
- {
- AnnotationValue flowId = ai.value("value");
- if (flowId != null && flowId.asString() != null)
- {
- AnnotationValue definingDocumentId = ai.value("definingDocumentId");
- recorder.registerFlowReference(ai.target().asClass().name().toString(),
- definingDocumentId == null ? "" : definingDocumentId.asString(),
- flowId.asString());
- }
- }
- }
-
- @BuildStep
- void produceApplicationArchiveMarker(
- BuildProducer<AdditionalApplicationArchiveMarkerBuildItem> additionalArchiveMarkers)
- {
- additionalArchiveMarkers.produce(new AdditionalApplicationArchiveMarkerBuildItem("org/primefaces/component"));
- additionalArchiveMarkers.produce(new AdditionalApplicationArchiveMarkerBuildItem("javax/faces/component"));
- additionalArchiveMarkers.produce(new AdditionalApplicationArchiveMarkerBuildItem("org/apache/myfaces/view"));
- }
-
- @BuildStep
- @Record(ExecutionTime.STATIC_INIT)
- void registerForLimitedReflection(MyFacesRecorder recorder,
- BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
- CombinedIndexBuildItem combinedIndex)
- {
- List<String> classNames = new ArrayList<>();
- List<Class<?>> classes = new ArrayList<>();
-
- classNames.addAll(collectClassAndSubclasses(combinedIndex, Renderer.class.getName()));
- classNames.addAll(collectClassAndSubclasses(combinedIndex, ClientBehaviorRenderer.class.getName()));
- classNames.addAll(collectClassAndSubclasses(combinedIndex, javax.el.ValueExpression.class.getName()));
- classNames.addAll(collectClassAndSubclasses(combinedIndex, SystemEvent.class.getName()));
- classNames.addAll(collectClassAndSubclasses(combinedIndex, FacesContext.class.getName()));
- classNames.addAll(collectClassAndSubclasses(combinedIndex, Application.class.getName()));
-
- for (String factory : FACTORIES)
- {
- classNames.addAll(collectClassAndSubclasses(combinedIndex, factory));
- }
-
- classNames.addAll(Arrays.asList(
- "org.primefaces.config.PrimeEnvironment",
- "com.lowagie.text.pdf.MappedRandomAccessFile",
- "org.apache.myfaces.application._ApplicationUtils",
- "com.sun.el.util.ReflectionUtil",
- "com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl",
- "org.primefaces.util.MessageFactory",
- "javax.faces.component._DeltaStateHelper",
- "javax.faces.component._DeltaStateHelper$InternalMap"));
-
- classes.addAll(Arrays.asList(
- DefaultWebConfigProviderFactory.class,
- ErrorPageWriter.class,
- DocumentBuilderFactoryImpl.class,
- FuncLocalPart.class,
- FuncNot.class,
- MyFacesContainerInitializer.class,
- RestoreViewSupport.class,
- ExceptionQueuedEventContext.class,
- FacesConfigurator.class,
- FaceletsInitilializer.class,
- TagLibraryConfig.class,
- String.class,
- ViewScopeProxyMap.class,
- SAXCompiler.class,
- StateUtils.class));
-
- reflectiveClass.produce(
- new ReflectiveClassBuildItem(false, false, classNames.toArray(new String[classNames.size()])));
- reflectiveClass.produce(
- new ReflectiveClassBuildItem(false, false, classes.toArray(new Class[classes.size()])));
- }
-
- @BuildStep
- @Record(ExecutionTime.STATIC_INIT)
- void registerForMethodReflection(MyFacesRecorder recorder, BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
- CombinedIndexBuildItem combinedIndex)
- {
- List<String> classNames = new ArrayList<>();
- List<Class<?>> classes = new ArrayList<>();
-
- classNames.addAll(collectClassAndSubclasses(combinedIndex, TagHandler.class.getName()));
- classNames.addAll(collectClassAndSubclasses(combinedIndex, ConverterHandler.class.getName()));
- classNames.addAll(collectClassAndSubclasses(combinedIndex, ComponentHandler.class.getName()));
- classNames.addAll(collectClassAndSubclasses(combinedIndex, ValidatorHandler.class.getName()));
- classNames.addAll(collectClassAndSubclasses(combinedIndex, UIComponent.class.getName()));
- classNames.addAll(collectClassAndSubclasses(combinedIndex, Converter.class.getName()));
- classNames.addAll(collectClassAndSubclasses(combinedIndex, Validator.class.getName()));
- classNames.addAll(collectClassAndSubclasses(combinedIndex, Behavior.class.getName()));
- classNames.addAll(collectClassAndSubclasses(combinedIndex, ELResolver.class.getName()));
- classNames.addAll(collectClassAndSubclasses(combinedIndex, MethodRule.class.getName()));
- classNames.addAll(collectClassAndSubclasses(combinedIndex, MetaRuleset.class.getName()));
- classNames.addAll(collectClassAndSubclasses(combinedIndex, "org.primefaces.component.api.Widget"));
- classNames.addAll(Arrays.asList(
- "org.primefaces.util.ComponentUtils",
- "org.primefaces.expression.SearchExpressionUtils",
- "org.primefaces.util.SecurityUtils",
- "org.primefaces.util.LangUtils",
- "javax.faces._FactoryFinderProviderFactory"));
-
- classes.addAll(Arrays.asList(
- ClassUtils.class,
- FactoryFinderProviderFactory.class,
- ComponentSupport.class,
- QuarkusFactoryFinderProvider.class,
- ELResolverBuilderForFaces.class,
- AbstractFacesInitializer.class,
- ExternalContextUtils.class,
- BeanEntry.class));
-
- reflectiveClass.produce(
- new ReflectiveClassBuildItem(true, false, classNames.toArray(new String[classNames.size()])));
- reflectiveClass.produce(
- new ReflectiveClassBuildItem(true, false, classes.toArray(new Class[classes.size()])));
- }
-
-
- @BuildStep
- @Record(ExecutionTime.STATIC_INIT)
- void registerForFieldReflection(MyFacesRecorder recorder, BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
- CombinedIndexBuildItem combinedIndex)
- {
- reflectiveClass.produce(new ReflectiveClassBuildItem(true, true,
- "javax.faces.context._MyFacesExternalContextHelper"));
- }
-
- @BuildStep
- void substrateResourceBuildItems(BuildProducer<NativeImageResourceBuildItem> nativeImageResourceProducer,
- BuildProducer<NativeImageResourceBundleBuildItem> resourceBundleBuildItem)
- {
- nativeImageResourceProducer
- .produce(new NativeImageResourceBuildItem("META-INF/maven/org.primefaces/primefaces/pom.properties"));
- nativeImageResourceProducer.produce(new NativeImageResourceBuildItem(
- "META-INF/rsc/myfaces-dev-error.xml",
- "META-INF/rsc/myfaces-dev-debug.xml",
- "org/apache/myfaces/resource/default.dtd",
- "org/apache/myfaces/resource/datatypes.dtd",
- "META-INF/web-fragment.xml",
- "META-INF/resources/org/apache/myfaces/windowId/windowhandler.html",
- "org/apache/myfaces/resource/facelet-taglib_1_0.dtd",
- "org/apache/myfaces/resource/javaee_5.xsd",
- "org/apache/myfaces/resource/web-facelettaglibrary_2_0.xsd",
- "org/apache/myfaces/resource/XMLSchema.dtd",
- "org/apache/myfaces/resource/facesconfig_1_0.dtd",
- "org/apache/myfaces/resource/web-facesconfig_1_1.dtd",
- "org/apache/myfaces/resource/web-facesconfig_1_2.dtd",
- "org/apache/myfaces/resource/web-facesconfig_2_0.dtd",
- "org/apache/myfaces/resource/web-facesconfig_2_1.dtd",
- "org/apache/myfaces/resource/web-facesconfig_2_2.dtd",
- "org/apache/myfaces/resource/web-facesconfig_2_3.dtd",
- "org/apache/myfaces/resource/web-facesconfig_3_0.dtd",
- "org/apache/myfaces/resource/xml.xsd",
- "META-INF/rsc/myfaces-dev-error-include.xml",
- "META-INF/services/javax.servlet.ServletContainerInitializer"));
-
- resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages"));
- resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_ar"));
- resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_ca"));
- resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_cs"));
- resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_de"));
- resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_en"));
- resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_es"));
- resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_fr"));
- resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_it"));
- resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_ja"));
- resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_mt"));
- resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_nl"));
- resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_pl"));
- resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_pt_PR"));
- resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_ru"));
- resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_sk"));
- resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_zh_CN"));
- resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_zh_HK"));
- resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_zh_TW"));
- resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.el.PrivateMessages"));
- resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.servlet.LocalStrings"));
- resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.el.LocalStrings"));
- resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.primefaces.Messages"));
- resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.primefaces.Messages_en"));
- }
-
- public List<String> collectClassAndSubclasses(CombinedIndexBuildItem combinedIndex, String className)
- {
- List<String> classes = combinedIndex.getIndex()
- .getAllKnownSubclasses(DotName.createSimple(className))
- .stream()
- .map(ClassInfo::toString)
- .collect(Collectors.toList());
- classes.add(className);
- return classes;
- }
-
- @BuildStep
- @Record(ExecutionTime.STATIC_INIT)
- void registerWebappClassesForReflection(MyFacesRecorder recorder,
- BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
- CombinedIndexBuildItem combinedIndex)
- {
- List<String> classNames = new ArrayList<>();
- classNames.addAll(Arrays.asList(
- "org.apache.myfaces.core.extensions.quarkus.showcase.view.LazyView",
- "org.apache.myfaces.core.extensions.quarkus.showcase.view.LazyView_ClientProxy",
- "org.apache.myfaces.core.extensions.quarkus.showcase.view.Car",
- "org.apache.myfaces.core.extensions.quarkus.showcase.view.LazyCarDataModel",
- "org.apache.myfaces.core.extensions.quarkus.showcase.view.CarService",
- "org.apache.myfaces.core.extensions.quarkus.showcase.view.LazySorter"));
- reflectiveClass.produce(
- new ReflectiveClassBuildItem(true, false, classNames.toArray(new String[classNames.size()])));
-
- reflectiveClass.produce(new ReflectiveClassBuildItem(true, true,
- "org.apache.myfaces.core.extensions.quarkus.showcase.view.LazyView_ClientProxy"));
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.myfaces.core.extensions.quarkus.deployment;
+
+import com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl;
+import com.sun.org.apache.xpath.internal.functions.FuncLocalPart;
+import com.sun.org.apache.xpath.internal.functions.FuncNot;
+import java.io.IOException;
+import java.util.Optional;
+
+import javax.faces.application.ProjectStage;
+import javax.faces.application.StateManager;
+import javax.faces.application.ViewHandler;
+import javax.faces.component.FacesComponent;
+import javax.faces.component.behavior.FacesBehavior;
+import javax.faces.convert.FacesConverter;
+import javax.faces.flow.FlowScoped;
+import javax.faces.flow.builder.FlowDefinition;
+import javax.faces.model.FacesDataModel;
+import javax.faces.push.PushContext;
+import javax.faces.render.FacesBehaviorRenderer;
+import javax.faces.render.FacesRenderer;
+import javax.faces.validator.FacesValidator;
+import javax.faces.view.ViewScoped;
+import javax.faces.view.facelets.FaceletsResourceResolver;
+import javax.faces.webapp.FacesServlet;
+
+import org.apache.myfaces.cdi.FacesScoped;
+import org.apache.myfaces.cdi.JsfApplicationArtifactHolder;
+import org.apache.myfaces.cdi.JsfArtifactProducer;
+import org.apache.myfaces.cdi.config.FacesConfigBeanHolder;
+import org.apache.myfaces.cdi.model.FacesDataModelManager;
+import org.apache.myfaces.cdi.view.ViewScopeBeanHolder;
+import org.apache.myfaces.cdi.view.ViewTransientScoped;
+import org.apache.myfaces.config.MyfacesConfig;
+import org.apache.myfaces.config.annotation.CdiAnnotationProviderExtension;
+import org.apache.myfaces.config.element.NamedEvent;
+import org.apache.myfaces.core.extensions.quarkus.runtime.exception.QuarkusExceptionHandlerFactory;
+import org.apache.myfaces.flow.cdi.FlowBuilderFactoryBean;
+import org.apache.myfaces.flow.cdi.FlowScopeBeanHolder;
+import org.apache.myfaces.push.cdi.PushContextFactoryBean;
+import org.apache.myfaces.push.cdi.WebsocketApplicationBean;
+import org.apache.myfaces.push.cdi.WebsocketChannelTokenBuilderBean;
+import org.apache.myfaces.push.cdi.WebsocketSessionBean;
+import org.apache.myfaces.push.cdi.WebsocketViewBean;
+import org.apache.myfaces.webapp.StartupServletContextListener;
+import org.eclipse.microprofile.config.Config;
+import org.eclipse.microprofile.config.ConfigProvider;
+import org.jboss.jandex.AnnotationInstance;
+import org.jboss.jandex.AnnotationValue;
+import org.jboss.jandex.DotName;
+
+import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
+import io.quarkus.arc.deployment.BeanDefiningAnnotationBuildItem;
+import io.quarkus.arc.deployment.BeanRegistrarBuildItem;
+import io.quarkus.arc.deployment.BeanRegistrationPhaseBuildItem;
+import io.quarkus.arc.deployment.ContextRegistrarBuildItem;
+import io.quarkus.arc.processor.ContextRegistrar;
+import io.quarkus.deployment.annotations.BuildProducer;
+import io.quarkus.deployment.annotations.BuildStep;
+import io.quarkus.deployment.annotations.ExecutionTime;
+import io.quarkus.deployment.annotations.Record;
+import io.quarkus.deployment.builditem.AdditionalApplicationArchiveMarkerBuildItem;
+import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
+import io.quarkus.deployment.builditem.FeatureBuildItem;
+import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem;
+import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBundleBuildItem;
+import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
+import org.apache.myfaces.core.extensions.quarkus.runtime.MyFacesRecorder;
+import org.apache.myfaces.core.extensions.quarkus.runtime.QuarkusFacesInitilializer;
+import org.apache.myfaces.core.extensions.quarkus.runtime.scopes.QuarkusFacesScopeContext;
+import org.apache.myfaces.core.extensions.quarkus.runtime.scopes.QuarkusFlowScopedContext;
+import org.apache.myfaces.core.extensions.quarkus.runtime.scopes.QuarkusViewScopeContext;
+import org.apache.myfaces.core.extensions.quarkus.runtime.scopes.QuarkusViewTransientScopeContext;
+import org.apache.myfaces.core.extensions.quarkus.runtime.spi.QuarkusInjectionProvider;
+import io.quarkus.runtime.LaunchMode;
+import io.quarkus.runtime.configuration.ProfileManager;
+import io.quarkus.undertow.deployment.ListenerBuildItem;
+import io.quarkus.undertow.deployment.ServletBuildItem;
+import io.quarkus.undertow.deployment.ServletInitParamBuildItem;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.el.ELResolver;
+import javax.faces.FactoryFinder;
+import javax.faces.application.Application;
+import javax.faces.component.UIComponent;
+import javax.faces.component.behavior.Behavior;
+import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
+import javax.faces.event.ExceptionQueuedEventContext;
+import javax.faces.event.SystemEvent;
+import javax.faces.render.ClientBehaviorRenderer;
+import javax.faces.render.Renderer;
+import javax.faces.validator.Validator;
+import javax.faces.view.facelets.ComponentHandler;
+import javax.faces.view.facelets.ConverterHandler;
+import javax.faces.view.facelets.MetaRuleset;
+import javax.faces.view.facelets.TagHandler;
+import javax.faces.view.facelets.ValidatorHandler;
+import org.apache.myfaces.application.viewstate.StateUtils;
+import org.apache.myfaces.cdi.util.BeanEntry;
+import org.apache.myfaces.config.FacesConfigurator;
+import org.apache.myfaces.core.extensions.quarkus.runtime.spi.QuarkusFactoryFinderProvider;
+import org.apache.myfaces.el.ELResolverBuilderForFaces;
+import org.apache.myfaces.lifecycle.RestoreViewSupport;
+import org.apache.myfaces.renderkit.ErrorPageWriter;
+import org.apache.myfaces.spi.FactoryFinderProviderFactory;
+import org.apache.myfaces.spi.impl.DefaultWebConfigProviderFactory;
+import org.apache.myfaces.util.ExternalContextUtils;
+import org.apache.myfaces.util.lang.ClassUtils;
+import org.apache.myfaces.view.ViewScopeProxyMap;
+import org.apache.myfaces.view.facelets.compiler.SAXCompiler;
+import org.apache.myfaces.view.facelets.compiler.TagLibraryConfig;
+import org.apache.myfaces.view.facelets.tag.MethodRule;
+import org.apache.myfaces.view.facelets.tag.jsf.ComponentSupport;
+import org.apache.myfaces.webapp.AbstractFacesInitializer;
+import org.apache.myfaces.webapp.FaceletsInitilializer;
+import org.apache.myfaces.webapp.MyFacesContainerInitializer;
+import org.jboss.jandex.ClassInfo;
+
+class MyFacesProcessor
+{
+
+ private static final Class[] BEAN_CLASSES =
+ {
+ JsfApplicationArtifactHolder.class,
+ JsfArtifactProducer.class,
+ FacesConfigBeanHolder.class,
+ FacesDataModelManager.class,
+ ViewScopeBeanHolder.class,
+ CdiAnnotationProviderExtension.class,
+ PushContextFactoryBean.class,
+ WebsocketChannelTokenBuilderBean.class,
+ WebsocketSessionBean.class,
+ WebsocketViewBean.class,
+ WebsocketApplicationBean.class,
+ FlowBuilderFactoryBean.class,
+ FlowScopeBeanHolder.class
+ };
+
+ private static final String[] BEAN_DEFINING_ANNOTATION_CLASSES =
+ {
+ FacesComponent.class.getName(),
+ FacesBehavior.class.getName(),
+ FacesConverter.class.getName(),
+ FacesValidator.class.getName(),
+ FacesRenderer.class.getName(),
+ NamedEvent.class.getName(),
+ FacesBehaviorRenderer.class.getName(),
+ FaceletsResourceResolver.class.getName(),
+ FlowDefinition.class.getName()
+ };
+
+ private static final String[] FACTORIES =
+ {
+ FactoryFinder.APPLICATION_FACTORY,
+ FactoryFinder.EXCEPTION_HANDLER_FACTORY,
+ FactoryFinder.EXTERNAL_CONTEXT_FACTORY,
+ FactoryFinder.FACES_CONTEXT_FACTORY,
+ FactoryFinder.LIFECYCLE_FACTORY,
+ FactoryFinder.PARTIAL_VIEW_CONTEXT_FACTORY,
+ FactoryFinder.RENDER_KIT_FACTORY,
+ FactoryFinder.TAG_HANDLER_DELEGATE_FACTORY,
+ FactoryFinder.VIEW_DECLARATION_LANGUAGE_FACTORY,
+ FactoryFinder.VISIT_CONTEXT_FACTORY,
+ FactoryFinder.FACELET_CACHE_FACTORY,
+ FactoryFinder.FLASH_FACTORY,
+ FactoryFinder.FLOW_HANDLER_FACTORY,
+ FactoryFinder.CLIENT_WINDOW_FACTORY,
+ FactoryFinder.SEARCH_EXPRESSION_CONTEXT_FACTORY,
+ QuarkusExceptionHandlerFactory.class.getName()
+ };
+
+ @BuildStep
+ void buildFeature(BuildProducer<FeatureBuildItem> feature) throws IOException
+ {
+ feature.produce(new FeatureBuildItem("myfaces"));
+ }
+
+ @BuildStep
+ void buildServlet(BuildProducer<FeatureBuildItem> feature,
+ BuildProducer<ServletBuildItem> servlet,
+ BuildProducer<ListenerBuildItem> listener) throws IOException
+ {
+ servlet.produce(ServletBuildItem.builder("Faces Servlet", FacesServlet.class.getName())
+ .addMapping("*.xhtml")
+ .build());
+
+ // sometimes Quarkus doesn't scan web-fragments?! lets add it manually
+ listener.produce(new ListenerBuildItem(StartupServletContextListener.class.getName()));
+ }
+
+ @BuildStep
+ void buildCdiBeans(BuildProducer<AdditionalBeanBuildItem> additionalBean,
+ BuildProducer<BeanDefiningAnnotationBuildItem> beanDefiningAnnotation) throws IOException
+ {
+ for (Class<?> clazz : BEAN_CLASSES)
+ {
+ additionalBean.produce(AdditionalBeanBuildItem.unremovableOf(clazz));
+ }
+
+ for (String clazz : BEAN_DEFINING_ANNOTATION_CLASSES)
+ {
+ beanDefiningAnnotation.produce(new BeanDefiningAnnotationBuildItem(DotName.createSimple(clazz)));
+ }
+
+ }
+
+ @BuildStep
+ void buildCdiScopes(BuildProducer<ContextRegistrarBuildItem> contextRegistrar) throws IOException
+ {
+ contextRegistrar.produce(new ContextRegistrarBuildItem(new ContextRegistrar()
+ {
+ @Override
+ public void register(ContextRegistrar.RegistrationContext registrationContext)
+ {
+ registrationContext.configure(ViewScoped.class)
+ .normal()
+ .contextClass(QuarkusViewScopeContext.class)
+ .done();
+ registrationContext.configure(FacesScoped.class)
+ .normal()
+ .contextClass(QuarkusFacesScopeContext.class)
+ .done();
+ registrationContext.configure(ViewTransientScoped.class)
+ .normal()
+ .contextClass(QuarkusViewTransientScopeContext.class)
+ .done();
+ registrationContext.configure(FlowScoped.class)
+ .normal()
+ .contextClass(QuarkusFlowScopedContext.class)
+ .done();
+ }
+ }));
+ }
+
+ @BuildStep
+ void buildInitParams(BuildProducer<ServletInitParamBuildItem> initParam) throws IOException
+ {
+ initParam.produce(new ServletInitParamBuildItem(
+ MyfacesConfig.INJECTION_PROVIDER, QuarkusInjectionProvider.class.getName()));
+ initParam.produce(new ServletInitParamBuildItem(
+ MyfacesConfig.FACES_INITIALIZER, QuarkusFacesInitilializer.class.getName()));
+ initParam.produce(new ServletInitParamBuildItem(
+ MyfacesConfig.SUPPORT_JSP, "false"));
+ }
+
+ @BuildStep
+ void buildRecommendedInitParams(BuildProducer<ServletInitParamBuildItem> initParam) throws IOException
+ {
+ // user config
+ Config config = ConfigProvider.getConfig();
+
+ Optional<String> projectStage = resolveProjectStage(config);
+ initParam.produce(new ServletInitParamBuildItem(ProjectStage.PROJECT_STAGE_PARAM_NAME, projectStage.get()));
+
+ Optional<String> enableWebsocketsEndpoint = config.getOptionalValue(
+ PushContext.ENABLE_WEBSOCKET_ENDPOINT_PARAM_NAME,
+ String.class);
+ if (enableWebsocketsEndpoint.isPresent())
+ {
+ initParam.produce(new ServletInitParamBuildItem(PushContext.ENABLE_WEBSOCKET_ENDPOINT_PARAM_NAME,
+ enableWebsocketsEndpoint.get()));
+ }
+
+ // common
+ initParam.produce(new ServletInitParamBuildItem(
+ MyfacesConfig.LOG_WEB_CONTEXT_PARAMS, "false"));
+ initParam.produce(new ServletInitParamBuildItem(
+ StateManager.STATE_SAVING_METHOD_PARAM_NAME, StateManager.STATE_SAVING_METHOD_SERVER));
+ initParam.produce(new ServletInitParamBuildItem(
+ StateManager.SERIALIZE_SERVER_STATE_PARAM_NAME, "false"));
+
+ // perf
+ initParam.produce(new ServletInitParamBuildItem(
+ MyfacesConfig.CHECK_ID_PRODUCTION_MODE, "false"));
+ initParam.produce(new ServletInitParamBuildItem(
+ MyfacesConfig.EARLY_FLUSH_ENABLED, "true"));
+ initParam.produce(new ServletInitParamBuildItem(
+ MyfacesConfig.CACHE_EL_EXPRESSIONS, "alwaysRecompile"));
+ initParam.produce(new ServletInitParamBuildItem(
+ MyfacesConfig.COMPRESS_STATE_IN_SESSION, "false"));
+ initParam.produce(new ServletInitParamBuildItem(
+ MyfacesConfig.NUMBER_OF_VIEWS_IN_SESSION, "15"));
+ initParam.produce(new ServletInitParamBuildItem(
+ MyfacesConfig.NUMBER_OF_SEQUENTIAL_VIEWS_IN_SESSION, "3"));
+
+ // MyFaces uses default 0, which means always recompile
+ if (ProjectStage.valueOf(projectStage.get()) == ProjectStage.Development)
+ {
+ initParam.produce(new ServletInitParamBuildItem(
+ ViewHandler.FACELETS_REFRESH_PERIOD_PARAM_NAME, "1"));
+ }
+
+ // primefaces perf
+ initParam.produce(new ServletInitParamBuildItem(
+ "primefaces.SUBMIT", "partial"));
+ initParam.produce(new ServletInitParamBuildItem(
+ "primefaces.MOVE_SCRIPTS_TO_BOTTOM", "true"));
+ }
+
+ @BuildStep
+ @Record(ExecutionTime.STATIC_INIT)
+ void buildAnnotationProviderIntegration(MyFacesRecorder recorder, CombinedIndexBuildItem combinedIndex)
+ throws IOException
+ {
+ for (String clazz : BEAN_DEFINING_ANNOTATION_CLASSES)
+ {
+ combinedIndex.getIndex()
+ .getAnnotations(DotName.createSimple(clazz))
+ .stream()
+ .forEach(annotation -> recorder.registerAnnotatedClass(annotation.name().toString(),
+ annotation.target().asClass().name().toString()));
+ }
+ }
+
+ private Optional<String> resolveProjectStage(Config config)
+ {
+ Optional<String> projectStage = config.getOptionalValue(ProjectStage.PROJECT_STAGE_PARAM_NAME,
+ String.class);
+ if (!projectStage.isPresent())
+ {
+ projectStage = Optional.of(ProjectStage.Production.name());
+ if (LaunchMode.DEVELOPMENT.getDefaultProfile().equals(ProfileManager.getActiveProfile()))
+ {
+ projectStage = Optional.of(ProjectStage.Development.name());
+ }
+ else if (LaunchMode.TEST.getDefaultProfile().equals(ProfileManager.getActiveProfile()))
+ {
+ projectStage = Optional.of(ProjectStage.SystemTest.name());
+ }
+ }
+ return projectStage;
+ }
+
+ @BuildStep
+ void buildMangedPropertyProducers(BeanRegistrationPhaseBuildItem beanRegistrationPhase,
+ BuildProducer<BeanRegistrationPhaseBuildItem.BeanConfiguratorBuildItem> beanConfigurators)
+ throws IOException
+ {
+ ManagedPropertyBuildStep.build(beanRegistrationPhase, beanConfigurators);
+ }
+
+ @BuildStep
+ @Record(ExecutionTime.STATIC_INIT)
+ void buildFacesDataModels(MyFacesRecorder recorder,
+ BuildProducer<BeanRegistrarBuildItem> beanConfigurators,
+ CombinedIndexBuildItem combinedIndex) throws IOException
+ {
+ for (AnnotationInstance ai : combinedIndex.getIndex()
+ .getAnnotations(DotName.createSimple(FacesDataModel.class.getName())))
+ {
+ AnnotationValue forClass = ai.value("forClass");
+ if (forClass != null)
+ {
+ recorder.registerFacesDataModel(
+ ai.target().asClass().name().toString(),
+ forClass.asClass().name().toString());
+ }
+ }
+ }
+
+ @BuildStep
+ @Record(ExecutionTime.STATIC_INIT)
+ void buildFlowScopedMapping(MyFacesRecorder recorder,
+ CombinedIndexBuildItem combinedIndex) throws IOException
+ {
+ for (AnnotationInstance ai : combinedIndex.getIndex()
+ .getAnnotations(DotName.createSimple(FlowScoped.class.getName())))
+ {
+ AnnotationValue flowId = ai.value("value");
+ if (flowId != null && flowId.asString() != null)
+ {
+ AnnotationValue definingDocumentId = ai.value("definingDocumentId");
+ recorder.registerFlowReference(ai.target().asClass().name().toString(),
+ definingDocumentId == null ? "" : definingDocumentId.asString(),
+ flowId.asString());
+ }
+ }
+ }
+
+ @BuildStep
+ void produceApplicationArchiveMarker(
+ BuildProducer<AdditionalApplicationArchiveMarkerBuildItem> additionalArchiveMarkers)
+ {
+ additionalArchiveMarkers.produce(new AdditionalApplicationArchiveMarkerBuildItem("org/primefaces/component"));
+ additionalArchiveMarkers.produce(new AdditionalApplicationArchiveMarkerBuildItem("javax/faces/component"));
+ additionalArchiveMarkers.produce(new AdditionalApplicationArchiveMarkerBuildItem("org/apache/myfaces/view"));
+ }
+
+ @BuildStep
+ @Record(ExecutionTime.STATIC_INIT)
+ void registerForLimitedReflection(MyFacesRecorder recorder,
+ BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
+ CombinedIndexBuildItem combinedIndex)
+ {
+ List<String> classNames = new ArrayList<>();
+ List<Class<?>> classes = new ArrayList<>();
+
+ classNames.addAll(collectClassAndSubclasses(combinedIndex, Renderer.class.getName()));
+ classNames.addAll(collectClassAndSubclasses(combinedIndex, ClientBehaviorRenderer.class.getName()));
+ classNames.addAll(collectClassAndSubclasses(combinedIndex, javax.el.ValueExpression.class.getName()));
+ classNames.addAll(collectClassAndSubclasses(combinedIndex, SystemEvent.class.getName()));
+ classNames.addAll(collectClassAndSubclasses(combinedIndex, FacesContext.class.getName()));
+ classNames.addAll(collectClassAndSubclasses(combinedIndex, Application.class.getName()));
+
+ for (String factory : FACTORIES)
+ {
+ classNames.addAll(collectClassAndSubclasses(combinedIndex, factory));
+ }
+
+ classNames.addAll(Arrays.asList(
+ "org.primefaces.config.PrimeEnvironment",
+ "com.lowagie.text.pdf.MappedRandomAccessFile",
+ "org.apache.myfaces.application._ApplicationUtils",
+ "org.apache.el.ExpressionFactoryImpl",
+ "org.primefaces.util.MessageFactory",
+ "javax.faces.component._DeltaStateHelper",
+ "javax.faces.component._DeltaStateHelper$InternalMap"));
+
+ classes.addAll(Arrays.asList(
+ DefaultWebConfigProviderFactory.class,
+ ErrorPageWriter.class,
+ DocumentBuilderFactoryImpl.class,
+ FuncLocalPart.class,
+ FuncNot.class,
+ MyFacesContainerInitializer.class,
+ RestoreViewSupport.class,
+ ExceptionQueuedEventContext.class,
+ FacesConfigurator.class,
+ FaceletsInitilializer.class,
+ TagLibraryConfig.class,
+ String.class,
+ ViewScopeProxyMap.class,
+ SAXCompiler.class,
+ StateUtils.class));
+
+ reflectiveClass.produce(
+ new ReflectiveClassBuildItem(false, false, classNames.toArray(new String[classNames.size()])));
+ reflectiveClass.produce(
+ new ReflectiveClassBuildItem(false, false, classes.toArray(new Class[classes.size()])));
+ }
+
+ @BuildStep
+ @Record(ExecutionTime.STATIC_INIT)
+ void registerForMethodReflection(MyFacesRecorder recorder, BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
+ CombinedIndexBuildItem combinedIndex)
+ {
+ List<String> classNames = new ArrayList<>();
+ List<Class<?>> classes = new ArrayList<>();
+
+ classNames.addAll(collectClassAndSubclasses(combinedIndex, TagHandler.class.getName()));
+ classNames.addAll(collectClassAndSubclasses(combinedIndex, ConverterHandler.class.getName()));
+ classNames.addAll(collectClassAndSubclasses(combinedIndex, ComponentHandler.class.getName()));
+ classNames.addAll(collectClassAndSubclasses(combinedIndex, ValidatorHandler.class.getName()));
+ classNames.addAll(collectClassAndSubclasses(combinedIndex, UIComponent.class.getName()));
+ classNames.addAll(collectClassAndSubclasses(combinedIndex, ELResolver.class.getName()));
+ classNames.addAll(collectClassAndSubclasses(combinedIndex, MethodRule.class.getName()));
+ classNames.addAll(collectClassAndSubclasses(combinedIndex, MetaRuleset.class.getName()));
+ classNames.addAll(Arrays.asList(
+ "org.primefaces.util.ComponentUtils",
+ "org.primefaces.expression.SearchExpressionUtils",
+ "org.primefaces.util.SecurityUtils",
+ "org.primefaces.util.LangUtils",
+ "javax.faces._FactoryFinderProviderFactory"));
+
+ classNames.addAll(collectImplementors(combinedIndex, Converter.class.getName()));
+ classNames.addAll(collectImplementors(combinedIndex, Validator.class.getName()));
+ classNames.addAll(collectImplementors(combinedIndex, Behavior.class.getName()));
+
+
+ classes.addAll(Arrays.asList(
+ ClassUtils.class,
+ FactoryFinderProviderFactory.class,
+ ComponentSupport.class,
+ QuarkusFactoryFinderProvider.class,
+ ELResolverBuilderForFaces.class,
+ AbstractFacesInitializer.class,
+ ExternalContextUtils.class,
+ BeanEntry.class));
+
+ reflectiveClass.produce(
+ new ReflectiveClassBuildItem(true, false, classNames.toArray(new String[classNames.size()])));
+ reflectiveClass.produce(
+ new ReflectiveClassBuildItem(true, false, classes.toArray(new Class[classes.size()])));
+ }
+
+
+ @BuildStep
+ @Record(ExecutionTime.STATIC_INIT)
+ void registerForFieldReflection(MyFacesRecorder recorder, BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
+ CombinedIndexBuildItem combinedIndex)
+ {
+ reflectiveClass.produce(new ReflectiveClassBuildItem(true, true,
+ "javax.faces.context._MyFacesExternalContextHelper"));
+ }
+
+ @BuildStep
+ void substrateResourceBuildItems(BuildProducer<NativeImageResourceBuildItem> nativeImageResourceProducer,
+ BuildProducer<NativeImageResourceBundleBuildItem> resourceBundleBuildItem)
+ {
+ nativeImageResourceProducer
+ .produce(new NativeImageResourceBuildItem("META-INF/maven/org.primefaces/primefaces/pom.properties"));
+ nativeImageResourceProducer.produce(new NativeImageResourceBuildItem(
+ "META-INF/rsc/myfaces-dev-error.xml",
+ "META-INF/rsc/myfaces-dev-debug.xml",
+ "org/apache/myfaces/resource/default.dtd",
+ "org/apache/myfaces/resource/datatypes.dtd",
+ "META-INF/web-fragment.xml",
+ "META-INF/resources/org/apache/myfaces/windowId/windowhandler.html",
+ "org/apache/myfaces/resource/facelet-taglib_1_0.dtd",
+ "org/apache/myfaces/resource/javaee_5.xsd",
+ "org/apache/myfaces/resource/web-facelettaglibrary_2_0.xsd",
+ "org/apache/myfaces/resource/XMLSchema.dtd",
+ "org/apache/myfaces/resource/facesconfig_1_0.dtd",
+ "org/apache/myfaces/resource/web-facesconfig_1_1.dtd",
+ "org/apache/myfaces/resource/web-facesconfig_1_2.dtd",
+ "org/apache/myfaces/resource/web-facesconfig_2_0.dtd",
+ "org/apache/myfaces/resource/web-facesconfig_2_1.dtd",
+ "org/apache/myfaces/resource/web-facesconfig_2_2.dtd",
+ "org/apache/myfaces/resource/web-facesconfig_2_3.dtd",
+ "org/apache/myfaces/resource/web-facesconfig_3_0.dtd",
+ "org/apache/myfaces/resource/xml.xsd",
+ "META-INF/rsc/myfaces-dev-error-include.xml",
+ "META-INF/services/javax.servlet.ServletContainerInitializer"));
+
+ resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages"));
+ resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_ar"));
+ resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_ca"));
+ resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_cs"));
+ resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_de"));
+ resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_en"));
+ resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_es"));
+ resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_fr"));
+ resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_it"));
+ resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_ja"));
+ resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_mt"));
+ resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_nl"));
+ resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_pl"));
+ resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_pt_PR"));
+ resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_ru"));
+ resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_sk"));
+ resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_zh_CN"));
+ resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_zh_HK"));
+ resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.faces.Messages_zh_TW"));
+ resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.el.PrivateMessages"));
+ resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.servlet.LocalStrings"));
+ resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("javax.el.LocalStrings"));
+ resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.primefaces.Messages"));
+ resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.primefaces.Messages_en"));
+ }
+
+ public List<String> collectClassAndSubclasses(CombinedIndexBuildItem combinedIndex, String className)
+ {
+ List<String> classes = combinedIndex.getIndex()
+ .getAllKnownSubclasses(DotName.createSimple(className))
+ .stream()
+ .map(ClassInfo::toString)
+ .collect(Collectors.toList());
+ classes.add(className);
+ return classes;
+ }
+
+ public List<String> collectImplementors(CombinedIndexBuildItem combinedIndex, String className)
+ {
+ List<String> classes = combinedIndex.getIndex()
+ .getAllKnownImplementors(DotName.createSimple(className))
+ .stream()
+ .map(ClassInfo::toString)
+ .collect(Collectors.toList());
+ classes.add(className);
+ return classes;
+ }
+
+ @BuildStep
+ @Record(ExecutionTime.STATIC_INIT)
+ void registerWebappClassesForReflection(MyFacesRecorder recorder,
+ BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
+ CombinedIndexBuildItem combinedIndex)
+ {
+ List<String> classNames = new ArrayList<>();
+ classNames.addAll(Arrays.asList(
+ "org.apache.myfaces.core.extensions.quarkus.showcase.view.LazyView",
+ "org.apache.myfaces.core.extensions.quarkus.showcase.view.LazyView_ClientProxy",
+ "org.apache.myfaces.core.extensions.quarkus.showcase.view.Car",
+ "org.apache.myfaces.core.extensions.quarkus.showcase.view.LazyCarDataModel",
+ "org.apache.myfaces.core.extensions.quarkus.showcase.view.CarService",
+ "org.apache.myfaces.core.extensions.quarkus.showcase.view.LazySorter"));
+ reflectiveClass.produce(
+ new ReflectiveClassBuildItem(true, false, classNames.toArray(new String[classNames.size()])));
+
+ reflectiveClass.produce(new ReflectiveClassBuildItem(true, true,
+ "org.apache.myfaces.core.extensions.quarkus.showcase.view.LazyView_ClientProxy"));
+ }
+}
diff --git a/extensions/quarkus/pom.xml b/extensions/quarkus/pom.xml
index f1dd76c..006fe2c 100644
--- a/extensions/quarkus/pom.xml
+++ b/extensions/quarkus/pom.xml
@@ -37,6 +37,7 @@
<modules>
<module>deployment</module>
<module>runtime</module>
+ <module>showcase</module>
</modules>
<properties>
diff --git a/extensions/quarkus/runtime/pom.xml b/extensions/quarkus/runtime/pom.xml
index 1bb275d..ffcd6ab 100644
--- a/extensions/quarkus/runtime/pom.xml
+++ b/extensions/quarkus/runtime/pom.xml
@@ -74,6 +74,61 @@
<artifactId>quarkus-jsonp</artifactId>
<version>${quarkus.version}</version>
</dependency>
+ <dependency>
+ <groupId>jakarta.ejb</groupId>
+ <artifactId>jakarta.ejb-api</artifactId>
+ <version>3.2.5</version>
+ </dependency>
+ <dependency>
+ <groupId>jakarta.persistence</groupId>
+ <artifactId>jakarta.persistence-api</artifactId>
+ <version>2.2.2</version>
+ </dependency>
+ <dependency>
+ <groupId>jakarta.validation</groupId>
+ <artifactId>jakarta.validation-api</artifactId>
+ <version>2.0.2</version>
+ </dependency>
+ <dependency>
+ <groupId>jakarta.servlet.jsp.jstl</groupId>
+ <artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
+ <version>1.2.4</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-fileupload</groupId> <!-- primefaces fileupload, needed in quarkus native mode -->
+ <artifactId>commons-fileupload</artifactId>
+ <version>1.3.3</version>
+ </dependency>
+ <dependency>
+ <groupId>jakarta.xml.bind</groupId> <!-- java 11 support -->
+ <artifactId>jakarta.xml.bind-api</artifactId>
+ <version>2.3.2</version>
+ </dependency>
+ <dependency>
+ <groupId>com.googlecode.owasp-java-html-sanitizer</groupId> <!-- primefaces textEditor renderer -->
+ <artifactId>owasp-java-html-sanitizer</artifactId>
+ <version>20181114.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.poi</groupId> <!-- primefaces exporter -->
+ <artifactId>poi</artifactId>
+ <version>3.17</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.poi</groupId>
+ <artifactId>poi-ooxml</artifactId>
+ <version>3.17</version>
+ </dependency>
+ <dependency>
+ <groupId>com.rometools</groupId> <!-- primefaces feed -->
+ <artifactId>rome</artifactId>
+ <version>1.9.0</version>
+ </dependency>
+ <dependency>
+ <groupId>com.github.librepdf</groupId>
+ <artifactId>openpdf</artifactId>
+ <version>1.2.21</version>
+ </dependency>
</dependencies>
<build>
diff --git a/extensions/quarkus/showcase/README.md b/extensions/quarkus/showcase/README.md
new file mode 100644
index 0000000..7587c29
--- /dev/null
+++ b/extensions/quarkus/showcase/README.md
@@ -0,0 +1,35 @@
+# Quarkus MyFaces Showcase
+
+This sample application shows Quarkus Myfaces extension usage
+
+## Running
+
+`mvn clean package -DskipTests && java -jar ./target/quarkus-myfaces-showcase-1.0-SNAPSHOT-runner.jar`
+
+## Dev mode
+
+In [dev mode](https://quarkus.io/guides/maven-tooling#development-mode) you can easily debug and hot deploy your quarkus application:
+
+`mvn quarkus:dev`
+
+> Hot deployment also works for facelets pages
+
+## Native mode
+
+For native mode you need at least [graalvm 20](https://github.com/graalvm/graalvm-ce-builds/releases/tag/vm-20.0.0), see graalvm instalation [instructions here](https://quarkus.io/guides/building-native-image).
+
+Following is how to `build and run` the native image:
+
+`mvn clean package -Pnative && ./target/quarkus-myfaces-showcase-1.0-SNAPSHOT-runner`
+
+## Testing
+
+Tests use [HTMLUnit](https://github.com/HtmlUnit/htmlunit) to retrieve web pages and assert their content.
+
+A `mvn clean test` will run JVM mode tests
+
+For `native mode ` tests use:
+
+```
+mvn verify -Pnative
+```
\ No newline at end of file
diff --git a/extensions/quarkus/showcase/pom.xml b/extensions/quarkus/showcase/pom.xml
index 57abf1b..90823ad 100644
--- a/extensions/quarkus/showcase/pom.xml
+++ b/extensions/quarkus/showcase/pom.xml
@@ -59,18 +59,34 @@
<artifactId>myfaces-quarkus-runtime</artifactId>
<version>${myfaces.version}</version>
</dependency>
-
<dependency>
<groupId>org.primefaces</groupId>
<artifactId>primefaces</artifactId>
<version>7.0</version>
</dependency>
-
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
+ <dependency>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-junit5</artifactId>
+ <version>${quarkus.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>net.sourceforge.htmlunit</groupId>
+ <artifactId>htmlunit</artifactId>
+ <version>2.35.0</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
+ <version>3.6.2</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
diff --git a/extensions/quarkus/showcase/src/main/java/org/apache/myfaces/core/extensions/quarkus/showcase/view/InputController.java b/extensions/quarkus/showcase/src/main/java/org/apache/myfaces/core/extensions/quarkus/showcase/view/InputController.java
index 4afef5e..ca9a3ba 100644
--- a/extensions/quarkus/showcase/src/main/java/org/apache/myfaces/core/extensions/quarkus/showcase/view/InputController.java
+++ b/extensions/quarkus/showcase/src/main/java/org/apache/myfaces/core/extensions/quarkus/showcase/view/InputController.java
@@ -30,7 +30,7 @@
@Inject
@ManagedProperty(value = "#{carService}")
- private CarService carService;
+ CarService carService;
private String val;
diff --git a/extensions/quarkus/showcase/src/main/java/org/apache/myfaces/core/extensions/quarkus/showcase/view/LazySorter.java b/extensions/quarkus/showcase/src/main/java/org/apache/myfaces/core/extensions/quarkus/showcase/view/LazySorter.java
index 36bf76b..69167d0 100644
--- a/extensions/quarkus/showcase/src/main/java/org/apache/myfaces/core/extensions/quarkus/showcase/view/LazySorter.java
+++ b/extensions/quarkus/showcase/src/main/java/org/apache/myfaces/core/extensions/quarkus/showcase/view/LazySorter.java
@@ -21,6 +21,8 @@
import java.util.Comparator;
import org.primefaces.model.SortOrder;
+import static org.apache.commons.lang3.StringUtils.capitalize;
+
public class LazySorter implements Comparator<Car> {
private String sortField;
@@ -34,15 +36,15 @@
@Override
public int compare(Car car1, Car car2) {
try {
- Object value1 = Car.class.getField(this.sortField).get(car1);
- Object value2 = Car.class.getField(this.sortField).get(car2);
+ Object value1 = Car.class.getMethod("get"+capitalize(this.sortField)).invoke(car1);
+ Object value2 = Car.class.getMethod("get"+capitalize(this.sortField)).invoke(car2);
int value = ((Comparable) value1).compareTo(value2);
return SortOrder.ASCENDING.equals(sortOrder) ? value : -1 * value;
}
catch(Exception e) {
- throw new RuntimeException();
+ throw new RuntimeException(e);
}
}
}
diff --git a/extensions/quarkus/showcase/src/main/java/org/apache/myfaces/core/extensions/quarkus/showcase/view/LazyView.java b/extensions/quarkus/showcase/src/main/java/org/apache/myfaces/core/extensions/quarkus/showcase/view/LazyView.java
index 9d8b664..e83e5d9 100644
--- a/extensions/quarkus/showcase/src/main/java/org/apache/myfaces/core/extensions/quarkus/showcase/view/LazyView.java
+++ b/extensions/quarkus/showcase/src/main/java/org/apache/myfaces/core/extensions/quarkus/showcase/view/LazyView.java
@@ -37,7 +37,7 @@
private Car selectedCar;
@Inject
- private CarService service;
+ CarService service;
@PostConstruct
public void init() {
diff --git a/extensions/quarkus/showcase/src/main/java/org/apache/myfaces/core/extensions/quarkus/showcase/view/MethodHandleELResolverBean.java b/extensions/quarkus/showcase/src/main/java/org/apache/myfaces/core/extensions/quarkus/showcase/view/MethodHandleELResolverBean.java
index 1c4a5aa..f2e15f4 100644
--- a/extensions/quarkus/showcase/src/main/java/org/apache/myfaces/core/extensions/quarkus/showcase/view/MethodHandleELResolverBean.java
+++ b/extensions/quarkus/showcase/src/main/java/org/apache/myfaces/core/extensions/quarkus/showcase/view/MethodHandleELResolverBean.java
@@ -33,7 +33,7 @@
public class MethodHandleELResolverBean implements Serializable, PhaseListener {
@Inject
- private CarService service;
+ CarService service;
private List<Car> cars;
diff --git a/extensions/quarkus/showcase/src/main/java/org/apache/myfaces/core/extensions/quarkus/showcase/view/MyBacking.java b/extensions/quarkus/showcase/src/main/java/org/apache/myfaces/core/extensions/quarkus/showcase/view/MyBacking.java
index 67842a8..28e3fd7 100644
--- a/extensions/quarkus/showcase/src/main/java/org/apache/myfaces/core/extensions/quarkus/showcase/view/MyBacking.java
+++ b/extensions/quarkus/showcase/src/main/java/org/apache/myfaces/core/extensions/quarkus/showcase/view/MyBacking.java
@@ -27,7 +27,8 @@
@RequestScoped
public class MyBacking {
- @Inject private CarService carService;
+ @Inject
+ CarService carService;
private MyCollection<Car> cars;
diff --git a/extensions/quarkus/showcase/src/main/java/org/apache/myfaces/core/extensions/quarkus/showcase/view/MyValidator.java b/extensions/quarkus/showcase/src/main/java/org/apache/myfaces/core/extensions/quarkus/showcase/view/MyValidator.java
index 5d00659..7ee3370 100644
--- a/extensions/quarkus/showcase/src/main/java/org/apache/myfaces/core/extensions/quarkus/showcase/view/MyValidator.java
+++ b/extensions/quarkus/showcase/src/main/java/org/apache/myfaces/core/extensions/quarkus/showcase/view/MyValidator.java
@@ -28,7 +28,8 @@
@FacesValidator(value = "myVal", managed = true)
public class MyValidator implements Validator<String>{
- @Inject private CarService carService;
+ @Inject
+ CarService carService;
public MyValidator()
{
diff --git a/extensions/quarkus/showcase/src/main/resources/application.properties b/extensions/quarkus/showcase/src/main/resources/application.properties
index 8136836..cf94889 100644
--- a/extensions/quarkus/showcase/src/main/resources/application.properties
+++ b/extensions/quarkus/showcase/src/main/resources/application.properties
@@ -13,5 +13,7 @@
# limitations under the License.
quarkus.log.console.format=%s%n
-javax.faces.PROJECT_STAGE = Production
-javax.faces.ENABLE_WEBSOCKET_ENDPOINT=true
\ No newline at end of file
+javax.faces.PROJECT_STAGE=Development
+javax.faces.ENABLE_WEBSOCKET_ENDPOINT=true
+quarkus.log.console.level=INFO
+quarkus.log.file.path=/tmp/debug.log
\ No newline at end of file
diff --git a/extensions/quarkus/showcase/src/test/java/org/apache/myfaces/core/extensions/quarkus/showcase/QuarkusMyFacesNativeIT.java b/extensions/quarkus/showcase/src/test/java/org/apache/myfaces/core/extensions/quarkus/showcase/QuarkusMyFacesNativeIT.java
new file mode 100644
index 0000000..5674136
--- /dev/null
+++ b/extensions/quarkus/showcase/src/test/java/org/apache/myfaces/core/extensions/quarkus/showcase/QuarkusMyFacesNativeIT.java
@@ -0,0 +1,7 @@
+package org.apache.myfaces.core.extensions.quarkus.showcase;
+
+import io.quarkus.test.junit.NativeImageTest;
+
+@NativeImageTest
+public class QuarkusMyFacesNativeIT extends QuarkusMyFacesShowcaseTest {
+}
diff --git a/extensions/quarkus/showcase/src/test/java/org/apache/myfaces/core/extensions/quarkus/showcase/QuarkusMyFacesShowcaseTest.java b/extensions/quarkus/showcase/src/test/java/org/apache/myfaces/core/extensions/quarkus/showcase/QuarkusMyFacesShowcaseTest.java
new file mode 100644
index 0000000..d4fe663
--- /dev/null
+++ b/extensions/quarkus/showcase/src/test/java/org/apache/myfaces/core/extensions/quarkus/showcase/QuarkusMyFacesShowcaseTest.java
@@ -0,0 +1,43 @@
+package org.apache.myfaces.core.extensions.quarkus.showcase;
+
+import com.gargoylesoftware.htmlunit.BrowserVersion;
+import com.gargoylesoftware.htmlunit.NicelyResynchronizingAjaxController;
+import com.gargoylesoftware.htmlunit.WebClient;
+import com.gargoylesoftware.htmlunit.html.HtmlDivision;
+import com.gargoylesoftware.htmlunit.html.HtmlPage;
+import io.quarkus.test.common.http.TestHTTPResource;
+import io.quarkus.test.junit.QuarkusTest;
+import org.junit.jupiter.api.Test;
+
+import java.net.URL;
+
+import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
+
+@QuarkusTest
+public class QuarkusMyFacesShowcaseTest {
+
+ @TestHTTPResource
+ URL url;
+
+ @Test
+ public void shouldOpenIndexPage() throws Exception {
+ try (final WebClient webClient = new WebClient(BrowserVersion.CHROME)) {
+ webClient.getOptions().setJavaScriptEnabled(true);
+ webClient.getOptions().setCssEnabled(false);
+ webClient.getOptions().setUseInsecureSSL(true);
+ webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
+ webClient.getCookieManager().setCookiesEnabled(true);
+ webClient.setAjaxController(new NicelyResynchronizingAjaxController());
+ webClient.getCookieManager().setCookiesEnabled(true);
+
+ final HtmlPage page = webClient.getPage(url + "/index.xhtml");
+
+ final HtmlDivision datatable = (HtmlDivision) page.getElementById("form:carTable");
+
+ assertThat(datatable).isNotNull();
+ assertThat(datatable.getByXPath("//tr[contains(@role,'row') and contains(@class,'ui-datatable-selectable')]"))
+ .hasSize(10);
+
+ }
+ }
+}