How to enable struts2 convention plugin - struts2

The problem seems silly because I properly misunderstood the document. Basically I just want to run the hello-world actionless example according to this instruction by simply adding hello.jsp file into WEB-INF/content and then running localhost:8080/test/hello, but Struts keeps showing the exception java.lang.NoSuchMethodException: com.opensymphony.xwork2.ActionSupport.index().
So I wonder there is any configuration need to be done before running. I couldn't find any thing about configuration for hello-world example.
Could anyone suggest me correct way ? Thanks
Updated: here is project tree, no action, no any fancy.
├── pom.xml
└── src
└── main
├── resources
│   └── struts.xml
└── webapp
├── WEB-INF
│   ├── content
│   │   └── hello.jsp
│   └── web.xml
└── index.jsp
The dependencies in pom.xml
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.3.8</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-rest-plugin</artifactId>
<version>2.3.8</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-convention-plugin</artifactId>
<version>2.3.8</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-config-browser-plugin</artifactId>
<version>2.3.8</version>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty</artifactId>
<version>6.1.26</version>
</dependency>

You have mixed the Struts 2 Convention plugin with the Struts 2 REST plugin and that's why Struts 2 is looking for method called index() (default method for REST).
Remove the REST plugin - struts2-rest-plugin - and everything should work as expected.
If you want to mix Convention with REST consult the docs, eg. you can use struts.rest.namespace to distinguish REST part of the application from normal web application part.
EDIT
If you want to mix both parties - a normal web app and REST endpoints - you can consider using PrefixBasedActionMapper which allows use different mappers per url. Plus you should use PrefixBasedActionProxyFactory to use proper factories to construct actions that will match the url.

Related

Unable to resolve class JunitAdapter

I wrote a test where I am importing a class from package com/intel/epgsw/JunitAdapter.groovy
When I try to run the test, I get this error:
[ERROR] Failed to execute goal org.codehaus.gmavenplus:gmavenplus-plugin:1.5:testCompile (groovy) on project jenkinsfile-test-shared-library: Error occurred while calling a method on a Groovy class from classpath. InvocationTargetException: startup failed:
[ERROR] src/test/groovy/CloneTestSpec.groovy: 3: unable to resolve class src.com.intel.epgsw.JunitAdapter
[ERROR] # line 3, column 1.
[ERROR] import com.intel.epgsw.JunitAdapter
[ERROR] ^
Test file is present in: src/test/groovy
Class that needs to be imported: com/intel/epgsw/JunitAdapter.groovy
My test file is CloneTestSpec.groovy
Here is the tree :
src
│   ├── com
│   │   └── intel
│   │   ├── epgsw
│   │   │   ├── TestResultEnum.groovy
│   │   │   ├── **JunitAdapter.groovy**
│   │   │  
│   └── test
│   ├── com
│   │   └── intel
│   │   └── epgsw
│   ├── epgsw
│   │   └── FooBar98.groovy
│   ├── groovy
│   │   ├── **CloneTestSpec.groovy**
This is a section of my pom.xml
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
<executions>
<execution>
<configuration>
<testSourceDirectory>src/test/groovy</testSourceDirectory>
<includes>
<include>**/*Spec.java</include>
<include>**/*Spec.class</include>
<include>**/*Spec</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
<version>${groovy.gmaven.pluginVersion}</version>
<executions>
<execution>
<id>groovy</id>
<goals>
<goal>addTestSources</goal>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
<configuration>
<sources>
<source>
<directory>src</directory>
<includes>
<include>**/*.groovy</include>
</includes>
</source>
</sources>
<testSources>
<testSource>
<directory>src/test/groovy/com/intel/epgsw</directory>
<includes>
<include>**/*.groovy</include>
</includes>
</testSource>
</testSources>
</configuration>
</plugin>
</plugins>
Your directory layout is chaotic. Please move all your test classes into the src/test/groovy base folder. There, you create a directory structure according to your package structure. For example (I cannot say for sure without seeing the package declarations in each file), assuming that
all application classes are Java classes,
all test classes are Groovy classes and
all classes are in the exact same package com.intel.epgsw:
src
main
java
com
intel
epgsw
ApplicationClassA.java
ApplicationClassB.java
test
groovy
com
intel
epgsw
TestResultEnum.groovy
JunitAdapter.groovy
FooBar98.groovy
CloneTestSpec.groovy
If any of my above assumptions are false, you need to adjust the directory structure accordingly. But your chaotic directory layout with 3 different base directories causes the trouble you are facing. Please do learn some Java, Groovy and Maven basics, especially the Maven standard directory layout.

Maven scope in plugin' dependencies

I am using Maven 3.x (3.2.5) and my project use the maven-antrun-plugin with additional dependencies. While I understand the principle behind, I have trouble understanding the use of <scope /> in this case:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<!-- executions -->
<dependencies>
...
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.17</version>
<scope>runtime</scope>
</dependency>
...
</dependencies>
</plugin>
I am depending upon mysql-connector-java with a runtime scope, whereas other dependencies use default (compile) scope.
The maven-antrun-plugin is used to do something to various database (hence the dependency). However, since the project is not tied to a specific JDBC Driver, the driver is not added to the project dependencies. The Ant task runs with several driver as dependencies since it may use such database depending on the configuration (eg: one could use jdbc:mysql, other jdbc:oracle:thin, etc...).
To my understanding, since the plugin executes, maven ignore the scope.
Is that true ?
Note: I've read the Maven documentation, and this point is not discussed. I'm pretty sure it is ignored but I'd like insight before.

Filter services by path in swagger

I have a spring-boot application with some REST services grouped under /api path.
I have some other services grouped under /management path which I don't want them to be displayed in /v2/api-docs.
I use springfox dependencies to generate swagger documentation:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.6.1</version>
</dependency>
How can I filter out services starting with /management url in swagger json?
You will need to add tags to the definitions. There is no automated way that I know of
paths:
"/management":
get:
tags:
- Management
summary: Manages something
...
"/v2/api-docs:
get:
tags:
- Documentation
summary: Docs
...

Parent POM is taking the same version which I am giving in the module version

I have a multi module maven project for e.g.
A
B
C
D
E
Currently this project is working fine and have a single job to build all the modules and upload to the artifactory with some version for e.g. 4.0.0-.They are using versions:set -DnewVersion=4.0.0-${BUILD_NUMBER} from Jenkins job.Now my next task is to split this project into module so they dev team can build each module independetly but my issue is some modules is having the dependecy on other modules for e.g
Module B is having dependecy on module A and Module C.if I build the module A first then it generate the number 4.0.0-00001 and upload it to the artifactory and then I build the module C then it generate the build 4.0.0-00005.Now the question comes how could I build the module B which is having the dependency on module A and C.In my opinion I need to define the version of module A and C explicitly in the dependency section.
<dependency>
<groupId>com.xyz.engine</groupId>
<artifactId>A</artifactId>
<version>4.0.0-00005</version>
</dependency>
From my module POM I am calling my parent POM and In jenkins job I am giving
versions:set -DnewVersion=4.0.0-${BUILD_NUMBER} for versioning purpose if I explicity define the version of A module then it is also passing the same value to the Parent POM and searching for it which is not avilable.Below is my module POM file
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.truvenhealth.analyticsengine</groupId>
<artifactId>AnalyticsEngine</artifactId>
<version>4.0.0-00002</version>
</parent>
<artifactId>LicenseVerifier</artifactId>
<name>LicenseVerifier</name>
<packaging>jar</packaging>
<dependencies>
<!-- Modules dependencies -->
<dependency>
<groupId>com.xyz.engine</groupId>
<artifactId>Common</artifactId>
<version>4.0.0-00007</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
</dependency>
<!-- External dependencies -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>1.6.2</version>
</dependency>
<dependency>
<groupId>com.verhas</groupId>
<artifactId>license3j</artifactId>
<version>1.0.4</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
</resource>
</resources>
<plugins>
<!-- Plugin configurations inherited from the parent POM -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
it is taking the same value for Parent POM which I assigned to Common module .I am keeping the Parent POM in separate repository it should not take the same value it should only take that value which I am defining for the Parent POM and it should download it from their and provide all the values to module POM and the build should be created for module LicenseVerifier with different version.
If you have a multi module build which looks like this:
root (pom.xml parent of all modules)
+---- module-a (pom.xml)
+---- module-b (pom.xml)
+---- module-c (pom.xml)
+---- module-d (pom.xml)
To build a module separately you can do this via Maven like this:
mvn -pl module-a clean package
This will build the module-a only and get the dependencies of other modules from the remote repository. Or you can enhance that like this:
mvn -pl module-a -amd clean package
where the option -amd means --also-make-dependents. If a developer needs a particular state you can do this by a mvn install first and afterwards only build the module you would like to build.
A very important thing in relationship with multi module builds is to have the same version for all modules and the parent. So dependencies between those modules is no problem.
Starting with Maven 3.2.1 you can define the version via properties.
A simple change to prevent Maven from emitting warnings about versions
with property expressions. Allowed property expressions in versions
include ${revision}, ${changelist}, and ${sha1}. These properties can
be set externally, but eventually a mechanism will be created in Maven
where these properties can be injected in a standard way. For example
you may want to glean the current Git revision and inject that value
into ${sha1}. This is by no means a complete solution for continuous
delivery but is a step in the right direction.
Furthermore during development i would prefer the SNAPSHOT versions which the cleanup in the repository manager simpler. So in essence i don't any need to separate the modules which logicaly belong together.
Apart from that if you use the same version within your multimodule build you can use things like this: ${project.version} to define the version of a dependency which is part of the reactor.

Split organization name into nested folders using ivy:retrieve

In ivy I can set a retrieve pattern in order to copy all my dependencies somewhere I want to.
For example:
<ivy:retrieve pattern="${local-maven2-dir}/[organisation]/[module]/[revision]/[module]-[revision].[ext]" conf="compile" type="jar,bundle" sync="true"/>
I wonder is it possible to treat organization not as a folder, but as a set of nested folders, and keep in deepest folder (which is revision) the jar package, just like jars are stored in maven default repo.
So, basically I want to have jars located in paths like
com/yahoo/platform/yui/yuicompressor/2.4.7
and not like
com.yahoo.platform.yui/yuicompressor/2.4.7
PS: involving groovy scripting counts as a valid solution as well, it's just that I have no idea how can groovy be involved here.
Actually, it's quite easy and already documented in Ivy (look near the bottom of the page). You can use [orgPath]:
<ivy:retrieve conf="compile"
type="jar,bundle"
sync="true"
pattern="${local-maven2-dir}/[orgPath]/[module]-[revision].[ext]"/>
The following example uses groovy.
David W. offers a far simpler solution, relying on a new "orgPath" pattern token introduced in ivy 2.3.
Example
Produces the following output
├── build
│   ├── com
│   │   └── yahoo
│   │   └── platform
│   │   └── yui
│   │   └── yuicompressor
│   │   └── 2.4.7
│   │   └── yuicompressor-2.4.7.jar
│   └── rhino
│   └── js
│   └── 1.6R7
│   └── js-1.6R7.jar
├── build.xml
└── ivy.xml
build.xml
<project name="demo" default="retrieve" xmlns:ivy="antlib:org.apache.ivy.ant">
<target name="resolve">
<ivy:resolve/>
<ivy:cachepath pathid="build.path" conf="build"/>
</target>
<target name="retrieve" depends="resolve">
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy" classpathref="build.path"/>
<ivy:artifactproperty conf="compile" name="index.[module].[artifact]" value="[module].[artifact]"/>
<ivy:artifactproperty conf="compile" name="[module].[artifact].organisation" value="[organisation]"/>
<ivy:artifactproperty conf="compile" name="[module].[artifact].module" value="[module]"/>
<ivy:artifactproperty conf="compile" name="[module].[artifact].artifact" value="[artifact]"/>
<ivy:artifactproperty conf="compile" name="[module].[artifact].revision" value="[revision]"/>
<ivy:artifactproperty conf="compile" name="[module].[artifact].ext" value="[ext]"/>
<ivy:artifactproperty conf="compile" name="[module].[artifact].cachefile" value="${ivy.cache.dir}/[organisation]/[module]/jars/[artifact]-[revision].[ext]"/>
<groovy>
modules = properties.findAll { it.toString().startsWith("index.") }
modules.each { key, value ->
def organisation = properties[value+".organisation"].replace(".","/")
def module = properties[value+".module"]
def artifact = properties[value+".artifact"]
def revision = properties[value+".revision"]
def ext = properties[value+".ext"]
def cachefile = properties[value+".cachefile"]
ant.copy(file:cachefile, tofile:"build/${organisation}/${module}/${revision}/${artifact}-${revision}.${ext}")
}
</groovy>
</target>
</project>
ivy.xml
<ivy-module version="2.0">
<info organisation="com.myspotontheweb" module="demo"/>
<configurations>
<conf name="build" description="Build dependencies"/>
<conf name="compile" description="Compile classpath"/>
</configurations>
<dependencies>
<!-- build dependencies -->
<dependency org="org.codehaus.groovy" name="groovy-all" rev="2.1.1" conf="build->default"/>
<!-- compile dependencies -->
<dependency org="com.yahoo.platform.yui" name="yuicompressor" rev="2.4.7" conf="compile->default"/>
</dependencies>
</ivy-module>

Resources