Spring MVC implementation of WebApplicationInitializer - spring-mvc

I have already learned how to configure Spring MVC app with XML so I decided to go ahead.
I read documentation about WebApplicationInitializer and minimizing of XML in application configuration. But when I completed all preparations of the sample application I encountered with 404 page.
Further I put snippets of my code, please give me advices how to make #-based approach properly.
Config file:
package com.onet.init;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.UrlBasedViewResolver;
#Configuration
#ComponentScan("com.onet")
#EnableWebMvc
public class BaseConfig {
#Bean
public UrlBasedViewResolver setupViewResolver() {
UrlBasedViewResolver resolver = new UrlBasedViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
}
Initializer:
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration.Dynamic;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
public class Initializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(BaseConfig.class);
Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
servlet.addMapping("*.html");
servlet.setLoadOnStartup(1);
}
}
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>oneTest</groupId>
<artifactId>oneTest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>3.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
</project>
Controller:
package com.onet.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
#Controller
public class HelloController {
#RequestMapping(value="/hello")
public ModelAndView goToHelloWorld() {
return new ModelAndView("hello-world");
}
}
index.jsp
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Home page</title>
</head>
<body>
<h1>Home page</h1>
<p>This is a home page.</p>
<p>Say Hello</p>
</body>
</html>
So when I click on "Say Hello" link I get 404.
Entire project you can download from my drop-box.

i just checked the project in your dropbox. it seems to me, the structure of the project is wrong. you mixed maven-scructure with eclipse-structure. When you use maven, you put the webcontent in src/main/webapp... not in WebContent like you did. you can take a look here for more details on this topic.
short version:
move the files from WebContent to src/main/webapp and try again.
long version:
if you run mvn package and extract the resulting *.war from /target directory, you will see it lacks the files from WebContent directory. Maven expect those files to be in src/main/webapp. I assume you started by creating a "Dynamic Web Project" in eclipse. Eclipse expect the resources like *.jsp and co. to be located in WebContent, this is why calling index.jsp work. But when it comes to spring it failes, because hello-world.jsp is not located where it should be.
how to fix:
Start with moving the files from WebContent to src/main/webapp. then run mvn eclipse:eclipse -Dwtpversion=2.0. it will generate the configuration for eclipse (.classpath, .project, etc.). Refresh the project in Eclipse. Now it should work.

Related

Lazysodium for Java cannot initialize sodium object

Following the tutorial from documentation I added the lazysodium library with Maven but seem like lazycode is trying to load another class but cannot find it.
Error message
Exception in thread "main" java.lang.NoClassDefFoundError: co/libly/resourceloader/SharedLibraryLoader
at com.goterl.lazycode.lazysodium.utils.LibraryLoader.loadBundledLibrary(LibraryLoader.java:115)
at com.goterl.lazycode.lazysodium.utils.LibraryLoader.loadLibrary(LibraryLoader.java:84)
at com.goterl.lazycode.lazysodium.SodiumJava.<init>(SodiumJava.java:34)
at com.goterl.lazycode.lazysodium.SodiumJava.<init>(SodiumJava.java:23)
at aitmed.crypto.main(crypto.java:12)
This is my main class, I make the simplest class possible to just test the library.
package groupme;
import com.goterl.lazycode.lazysodium.*;
public class crypto {
public static void main(String args[]) {
LazySodiumJava lazySodium = new LazySodiumJava(new SodiumJava());
}
}
This is my pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>aitmed</groupId>
<artifactId>androidsdk</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<!-- required for jdk9 -->
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<java.version>1.11</java.version>
<maven.compiler.source>1.11</maven.compiler.source>
<maven.compiler.target>1.11</maven.compiler.target>
</properties>
<repositories>
<repository>
<id>lazysodium-java</id>
<url>https://dl.bintray.com/terl/lazysodium-maven</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.goterl.lazycode</groupId>
<artifactId>lazysodium-java</artifactId>
<version>4.2.3</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>5.4.0</version>
</dependency>
</dependencies>
</project>

Netbeans 9.0 with JavaFx 11 and JDK 11

I am trying to run JavaFX 11 on NetBeans 9
Since JDK 11 does not have JavaFX anymore I couldn't get NetBeans to run a JavaFX project, it says: "Failed to automatically set-up a JavaFX Platform."
I then downloaded the javafx11 from this website https://gluonhq.com/products/javafx/,
after following the tutorial I was able to compile and run a JavaFX class normally through terminal.
The only way I could add JavaFX is by using Maven, but I can't run the application even that it was built successfully.
Error: JavaFX runtime components are missing, and are required to run this application
Command execution failed.
Is there any other way to run JavaFX 11 with NetBeans? or maybe Eclipse?
Maybe a late answer, but, it is possible to have javafx 11 maven project + NetBeans 9.
Maven doesn't like extending Application in a main clas. You should use two classes:
Main.java:
public class Main {
public static void main(String[] args) {
MainApp.main(args);
}
}
MainApp.java:
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class MainApp extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Hello World!");
String a;
a = new String("test");
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
System.out.println("Hello World!");
}
});
StackPane root = new StackPane();
root.getChildren().add(btn);
primaryStage.setScene(new Scene(root, 300, 250));
primaryStage.show();
}
}
Your pom.xml should look like this:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>YOUR GROUP ID</groupId>
<artifactId>YOUR ARTIFACT ID</artifactId>
<version>YOUR VERSION</version>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>11</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-media</artifactId>
<version>11</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
<version>11</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>11</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>11</source>
<target>11</target>
<fork>true</fork>
<executable>PATH TO javac binary i.e. /usr/local/java/jdk-11.0.1/bin/javac</executable>
<compilerArgs>
<arg>-verbose</arg>
<arg>-Xlint:unchecked</arg>
</compilerArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>Main</mainClass>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<archive>
<manifest>
<mainClass>Main</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<name>YOUR ARTIFACT ID</name>
</project>
This will work in netbeans without any issues.
Basically, what you need to do is start new maven project and after you finish setting project just replace pom.xml.
This way your code will run from IDE, and will compile correctly so that you can run it from command line with java --jar. Also, you will be able to run NB debugger.
This error is shown since the Java 11 launcher checks if the main class extends javafx.application.Application. If that is the case, it is required to have the javafx.graphics module on the module-path.
Stolen from javafx documentation

Spring Boot WebFlux NettyServerCustomizer does not work

I have very simple application, I read I can use NettyServerCustomizer to customize NettyServer. But it does not work, implementation of the NettyServerCustomizer interface is not being called.
Project is generated by Spring Initializr
Code of application:
#SpringBootApplication
#RestController
#RequestMapping("/test")
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#GetMapping
public Mono<String> test() {
return Mono.just("test");
}
#Bean
public NettyServerCustomizer nettyCustomizer() {
return builder -> builder.port(9909);
}
}
pom
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Defining a bean of type NettyServerCustomizer doesn't have any effect by itself, you can get the desired result with WebServerFactoryCustomizer
#Bean
public WebServerFactoryCustomizer getWebServerFactoryCustomizer() {
WebServerFactoryCustomizer<ConfigurableReactiveWebServerFactory> customizer = factory -> factory.setPort(9909);
return customizer;
}
Also note that the port is also read from the Environment using the property server.port, which I think the cleanest way besides it has a great deal of flexibility regarding the source of the property value.
If you are wondering why NettyServerCustomizer doesn't work, a bit of digging in the code reveals that this class is not injected into NettyReactiveWebServerFactory in any way.

Inject Spring defined propery into controller

I am trying to inject property with value inside my controller by using Spring Framework servlet.xml config file. My controller starts like this
package lv.lu.meetings.portal.mvc.controller;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpSession;
import lv.lu.meetings.domain.jpa.User;
import lv.lu.meetings.domain.jpa.meeting.Attendance;
import lv.lu.meetings.domain.jpa.meeting.Invite;
import lv.lu.meetings.domain.jpa.meeting.InviteStatus;
import lv.lu.meetings.domain.jpa.meeting.Meeting;
import lv.lu.meetings.domain.jpa.notification.Notification;
import lv.lu.meetings.domain.redis.Friend;
import lv.lu.meetings.interfaces.service.NotificationService;
import lv.lu.meetings.interfaces.service.UserService;
import lv.lu.meetings.portal.mvc.WebConst;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
/**
* Controller for displaying application home page.
*
* Supports multiple tab views: Main, Friends, Notifications, Meetings.
*/
#Controller
public class HomePageController {
// limit meeting count
// defined in meetings-servlet.xml
private String limit;
public String getLimit() {
return limit;
}
public void setLimit(String limit) {
this.limit = limit;
}
My meetings-servlet.xml file is like this
<?xml version="1.0" encoding="UTF-8"?>
<!-- Spring Web application configuration file -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
<!-- Support for component autowiring -->
<context:component-scan base-package="lv.lu.meetings"/>
<!-- URL mapping for annotation-based Spring Web MVC controllers -->
<bean id="urlMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<list>
<ref bean="loginInterceptor"/>
</list>
</property>
</bean>
<!-- Limit output data -->
<bean id="HomePageController" class="lv.lu.meetings.portal.mvc.controller.HomePageController">
<property name="limit" value="10" />
</bean>
I'm getting error
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'urlMapping' defined in ServletContext resource [/WEB-INF/meetings-servlet.xml]: Initialization of bean failed; nested exception is java.lang.IllegalStateException: Cannot map handler 'HomePageController' to URL path [/home]: There is already handler of type [class lv.lu.meetings.portal.mvc.controller.HomePageController] mapped.
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:529)
It's definitely smth easy to configure, but i am new to Java and Spring Framework itself, so help is appreciated. Thanks!
You are currently creating 2 HomePageController beans. One from
<!-- Limit output data -->
<bean id="HomePageController" class="lv.lu.meetings.portal.mvc.controller.HomePageController">
<property name="limit" value="10" />
</bean>
and the other from
<context:component-scan base-package="lv.lu.meetings"/>
and the #Controller annotation on
#Controller
public class HomePageController {
Assuming you have a #RequestMapping handler method in this class, Spring will try to register it twice and fail since you can't have two handlers for the same URL.
Choose one or the other bean. If you want to go the annotation way, you can inject the value directly
#Value("10")
private String limit;
or use a property placeholder.
You can set the property with the #Value annotation reading a value from a property file (or whatever):
#Value("${my.limit}")
private String limit;
You can also exclude the HomePageController from the component scanning:
<context:component-scan base-package="lv.lu.meetings">
<context:exclude-filter type="regex" expression="HomePageController$"/>
</context:component-scan>

spring roo excel view

I am trying to output an Excel file as the view in Spring Roo 1.0.2
What is the quickest way to do this?
(Do I have to add new mapping etc?) At the moment I am using the default Roo AjaxUrlBasedViewResolver.
Thanks
I don't think there's a specific "Roo" way of doing this, but Spring MVC does have an AbstractExcelView class that uses Apache POI and doesn't cause any problems - I think it's the best you can hope for.
First create a view class that extends AbstractExcelView and implements the buildExcelDocument method:
import org.springframework.web.servlet.view.document.AbstractExcelView;
public class XlsView extends AbstractExcelView {
#Override
protected void buildExcelDocument(
Map<String, Object> model, HSSFWorkbook workbook,
HttpServletRequest request, HttpServletResponse response) throws Exception {
//Apache POI code to set up the HSSFWorkbook goes here
response.setHeader("Content-Disposition", "attachment; filename=\"file.xls\"");
}
}
Then add the following to your webmvc-config.xml. I don't think the position matters, but I have it below the section where my TilesConfigurer is listed:
<bean id="excelViewResolver" class="org.springframework.web.servlet.view.XmlViewResolver">
<property name="order" value="1"/>
<property name="location" value="/WEB-INF/views/views-excel.xml"/>
</bean>
Finally create views-excel.xml with the following in it:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<bean name="XlsView" class="com.your.package.XlsView"/>
</beans>

Resources