/*******************************************************************************
* Copyright (c) 2015 Development Gateway, Inc and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the MIT License (MIT)
* which accompanies this distribution, and is available at
* https://opensource.org/licenses/MIT
*
* Contributors:
* Development Gateway - initial API and implementation
*******************************************************************************/
package org.devgateway.toolkit.forms.wicket;
import java.math.BigDecimal;
import org.apache.wicket.Application;
import org.apache.wicket.ConverterLocator;
import org.apache.wicket.IConverterLocator;
import org.apache.wicket.Page;
import org.apache.wicket.authroles.authentication.AuthenticatedWebApplication;
import org.apache.wicket.authroles.authentication.AuthenticatedWebSession;
import org.apache.wicket.devutils.diskstore.DebugDiskDataStore;
import org.apache.wicket.markup.html.IPackageResourceGuard;
import org.apache.wicket.markup.html.SecurePackageResourceGuard;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.request.resource.caching.FilenameWithVersionResourceCachingStrategy;
import org.apache.wicket.request.resource.caching.NoOpResourceCachingStrategy;
import org.apache.wicket.request.resource.caching.version.CachingResourceVersion;
import org.apache.wicket.serialize.java.DeflatedJavaSerializer;
import org.apache.wicket.settings.RequestCycleSettings.RenderStrategy;
import org.apache.wicket.spring.injection.annot.SpringComponentInjector;
import org.apache.wicket.util.file.Folder;
import org.devgateway.toolkit.forms.service.SessionFinderService;
import org.devgateway.toolkit.forms.wicket.converters.NonNumericFilteredBigDecimalConverter;
import org.devgateway.toolkit.forms.wicket.page.BasePage;
import org.devgateway.toolkit.forms.wicket.page.Homepage;
import org.devgateway.toolkit.forms.wicket.page.user.LoginPage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.PropertySource;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.wicketstuff.annotation.scan.AnnotatedMountScanner;
import com.google.javascript.jscomp.CompilationLevel;
import de.agilecoders.wicket.core.Bootstrap;
import de.agilecoders.wicket.core.markup.html.RenderJavaScriptToFooterHeaderResponseDecorator;
import de.agilecoders.wicket.core.request.resource.caching.version.Adler32ResourceVersion;
import de.agilecoders.wicket.core.settings.BootstrapSettings;
import de.agilecoders.wicket.core.settings.IBootstrapSettings;
import de.agilecoders.wicket.extensions.javascript.GoogleClosureJavaScriptCompressor;
import de.agilecoders.wicket.extensions.javascript.YuiCssCompressor;
import de.agilecoders.wicket.extensions.markup.html.bootstrap.editor.SummernoteConfig;
import de.agilecoders.wicket.extensions.markup.html.bootstrap.editor.SummernoteFileStorage;
import de.agilecoders.wicket.extensions.markup.html.bootstrap.editor.SummernoteStoredImageResourceReference;
import de.agilecoders.wicket.less.BootstrapLess;
import de.agilecoders.wicket.webjars.WicketWebjars;
import nl.dries.wicket.hibernate.dozer.SessionFinderHolder;
/**
* The web application class also serves as spring boot starting point by using
* spring boot's EnableAutoConfiguration annotation and providing the main
* method.
*
* @author Stefan Kloe, mpostelnicu
*
*/
@EnableScheduling
@SpringBootApplication
@ComponentScan("org.devgateway.toolkit")
@PropertySource("classpath:/org/devgateway/toolkit/forms/application.properties")
public class FormsWebApplication extends AuthenticatedWebApplication {
public static final String STORAGE_ID = "fileStorage";
private static final String BASE_PACKAGE_FOR_PAGES = BasePage.class.getPackage().getName();
@Autowired
private ApplicationContext applicationContext;
@Autowired
private SessionFinderService sessionFinderService;
public static void main(final String[] args) {
SpringApplication.run(FormsWebApplication.class, args);
}
/**
* @see org.apache.wicket.Application#newConverterLocator() This adds the
* {@link NonNumericFilteredBigDecimalConverter} as the standard
* {@link BigDecimal} converter for ALL fields using this type accross
* the application
**/
@Override
protected IConverterLocator newConverterLocator() {
ConverterLocator locator = (ConverterLocator) super.newConverterLocator();
locator.set(BigDecimal.class, new NonNumericFilteredBigDecimalConverter());
return locator;
}
private void configureSummernote() {
// the folder where to store the images
Folder folder = new Folder(System.getProperty("java.io.tmpdir"), "bootstrap-summernote");
folder.mkdirs();
folder.deleteOnExit();
SummernoteConfig.addStorage(new SummernoteFileStorage(STORAGE_ID, folder));
// mount the resource reference responsible for image uploads
mountResource(SummernoteStoredImageResourceReference.SUMMERNOTE_MOUNT_PATH,
new SummernoteStoredImageResourceReference(STORAGE_ID));
}
/**
* provides page for default request
*/
@Override
public Class<? extends Page> getHomePage() {
return Homepage.class;
}
public static FormsWebApplication get() {
return (FormsWebApplication) Application.get();
}
/**
* configures wicket-bootstrap and installs the settings.
*/
private void configureBootstrap() {
WicketWebjars.install(this);
final IBootstrapSettings settings = new BootstrapSettings();
// specify an empty bootstrap css resource so that we can have more
// control when do we load the bootstrap styles.
// By default all pages will load bootstrap.css file and there are
// situations (like print page) when we don't need this styles.
// The boostrap.css file is loaded as dependency in MainCss Instance
// settings.setCssResourceReference(EmptyCss.INSTANCE);
settings.useCdnResources(true);
// use the default bootstrap theme
Bootstrap.install(this, settings);
BootstrapLess.install(this);
}
/**
* optimize wicket for a better web performance This will be invoked if the
* application is started with -Dwicket.configuration=deployment
*/
private void optimizeForWebPerformance() {
// add javascript files at the bottom of the page
setHeaderResponseDecorator(new RenderJavaScriptToFooterHeaderResponseDecorator("scripts-bucket"));
// This is only enabled for deployment configuration
// -Dwicket.configuration=deployment
// The default is Development, so this code is not used
if (usesDeploymentConfig()) {
getResourceSettings().setCachingStrategy(new FilenameWithVersionResourceCachingStrategy("-v-",
new CachingResourceVersion(new Adler32ResourceVersion())));
getResourceSettings().setJavaScriptCompressor(
new GoogleClosureJavaScriptCompressor(CompilationLevel.SIMPLE_OPTIMIZATIONS));
getResourceSettings().setCssCompressor(new YuiCssCompressor());
getFrameworkSettings().setSerializer(new DeflatedJavaSerializer(getApplicationKey()));
getMarkupSettings().setStripComments(true);
} else {
getResourceSettings().setCachingStrategy(new NoOpResourceCachingStrategy());
}
getRequestCycleSettings().setRenderStrategy(RenderStrategy.ONE_PASS_RENDER);
}
@Override
protected Class<? extends AuthenticatedWebSession> getWebSessionClass() {
return SSAuthenticatedWebSession.class;
}
/**
* <ul>
* <li>making the wicket components injectable by activating the
* SpringComponentInjector</li>
* <li>mounting the test page</li>
* <li>logging spring service method output to showcase working integration
* </li>
* </ul>
*/
@Override
protected void init() {
super.init();
// add allowed woff2 extension
IPackageResourceGuard packageResourceGuard = getResourceSettings().getPackageResourceGuard();
if (packageResourceGuard instanceof SecurePackageResourceGuard) {
SecurePackageResourceGuard guard = (SecurePackageResourceGuard) packageResourceGuard;
guard.addPattern("+*.woff2");
}
// this ensures that spring DI works for wicket components and pages
// see @SpringBean annotation
getComponentInstantiationListeners().add(new SpringComponentInjector(this, applicationContext));
// this will scan packages for pages with @MountPath annotations and
// automatically create URLs for them
new AnnotatedMountScanner().scanPackage(BASE_PACKAGE_FOR_PAGES).mount(this);
getApplicationSettings().setUploadProgressUpdatesEnabled(true);
getApplicationSettings().setAccessDeniedPage(Homepage.class);
// deactivate ajax debug mode
// getDebugSettings().setAjaxDebugModeEnabled(false);
configureBootstrap();
configureSummernote();
optimizeForWebPerformance();
// watch this using the URL
// http://.../wicket/internal/debug/diskDataStore
if (usesDevelopmentConfig()) {
DebugDiskDataStore.register(this);
}
SessionFinderHolder.setSessionFinder(sessionFinderService);
}
/*
* (non-Javadoc)
*
* @see
* org.apache.wicket.authroles.authentication.AuthenticatedWebApplication#
* getSignInPageClass()
*/
@Override
protected Class<? extends WebPage> getSignInPageClass() {
return LoginPage.class;
}
}