I am currently trying to write a maven plugin which should be able to create/process some resource files during the "generate-resources" phase. Everything works fine but during the process my plugin needs to read some other files as input, so I decided to use the Apache Maven File Management API to specify the input file paths. I set up everything like described in the In a MOJO example.
<plugin>
<groupId>my.groupId</groupId>
<artifactId>my-maven-plugin</artifactId>
<version>0.0.1-SNAPSHOT</version>
<executions>
<execution>
<goals>
<goal>mygoal</goal>
</goals>
<phase>generate-resources</phase>
</execution>
</executions>
<configuration>
<fileset>
<directory>${basedir}/src/main/resources</directory>
<includes>
<include>**/*.xml</include>
</includes>
</fileset>
</configuration>
</plugin>
But I am not able to retrieve the absolute Filepath of the files:
public void execute() throws MojoExecutionException {
FileSetManager fileSetManager = new FileSetManager();
for (String includedFile : fileSetManager.getIncludedFiles(fileset)) {
getLog().info(includedFile);
}
}
...as the result is just the filename like:
[INFO] --- my-maven-plugin:0.0.1-SNAPSHOT:mygoal (default) ---
[INFO] some-file-A.xml
[INFO] some-file-B.xml
I am also not able to concatenate the fileset.directory with the filename because FileSetManager does not contain a method to retrieve the fileset.directory value.
So how can I retrieve the absolute file path of the includes?
I found out that fileset.getDirectory() does the trick.
public void execute() throws MojoExecutionException {
FileSetManager fileSetManager = new FileSetManager();
for (String includedFile : fileSetManager.getIncludedFiles(fileset)) {
getLog().info(fileset.getDirectory() + File.separator + includedFile);
}
}
Related
I'm working on a multi-module Maven web project.
Let's say the structure looks something like this:
Project
Module1
Module2
Persist
log4j.properties
I managed to log all the log-entries into one file (placing the log4j.properties files into the project-persist module). So far, this is clear.
Now, there are some modules which I would like to separate the logs into other files.
Adding just a new appender (testAppender in the example) doesn't work for me because then I don't get the path of the .java file the log was written from.
If I write it like this:
Logger log = Logger.getLogger("testAppender");
I get something like this:
2017-276-06 15:00:00,032 [INFO ] Start rule activation. (testAppender)[__ejb-thread-pool3]
And this is what I want:
2016-06-06 15:00:00,032 [INFO ] Start rule activation. (Module1.src.main.java.somepkg.MyClass)[__ejb-thread-pool3]
Where MyClass is the .java file.
I also tried to add a completely new (independent) log4j.properties file to the Maven-modules (Module1 and Module2), just like in the Persist-module, I want to separate the logs from, with a different path to the .log file, but it logs only the entries from the maven tests - which is another problem I have, but one at a time.
Is there a way to add a new appender that will separate the log entries by the modules they're comming from and to have them printed in the .log file?
In the jar module, exclude the file from the jar:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.1</version>
<configuration>
<excludes>
<exclude>log4j.xml</exclude>
</excludes>
</configuration>
</plugin>
Use the buildhelper plugin to attach the log4j.xml to the build as a separate artifact
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<id>attach-artifacts</id>
<phase>package</phase>
<goals>
<goal>attach-artifact</goal>
</goals>
<configuration>
<artifacts>
<artifact>
<file>${project.build.outputDirectory}/log4j.xml</file>
<type>xml</type>
<classifier>log4j</classifier>
</artifact>
</artifacts>
</configuration>
</execution>
</executions>
</plugin>
Now in your war artifact, copy the xml to the output directory:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<phase>prepare-package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>${project.groupId}</groupId>
<artifactId>your.jar.project.artifactId</artifactId>
<version>${project.version}</version>
<type>xml</type>
<classifier>log4j</classifier>
<outputDirectory>${project.build.outputDirectory}
</outputDirectory>
<destFileName>log4j.xml</destFileName>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
But of course it would be easier to just put the file in [web-artifact]/src/main/resources in the first place :-)
So, I found a solution to this problem.
I made a class that gets a logger object and from the logger object I take the informations I need to seperate them.
I initilize the logger manually, kind of.
Hope this will help someone!
In every class where the Logger is used, I also call the initilizer.
public class ClassA{
private final Logger LOGGER = Logger.getLogger(ClassA.class);
static{
LOGGER.addAppender(LogConfig.init(LOGGER));
}
some code...
}
A here is what I did in the LogConfig class:
public class LogConfig {
public static RollingFileAppender init(Logger LOGGER) {
String logInfo = LOGGER.getClass().toString();
String loglevel = getLogLevel(logInfo);
String logClazz = getLogClazz(logInfo);
String logModule = getModule(logInfo);
PatternLayout PL = new PatternLayout("%d [%-5p] %m (%c)[%t]%n");
try {
if (logModule == "presentation") {
RollingFileAppender appender = new RollingFileAppender(PL, "PathToLogFile_1.log", true);
return appender;
}
else if (logModule == "business") {
RollingFileAppender appender = new RollingFileAppender(PL, "PathToLogFile_2.log", true);
return appender;
}
RollingFileAppender appender = new RollingFileAppender(PL, "PathToLogFile_3.log", true);
return appender;
}catch (IOException e) {
e.printStackTrace();
}
return null;
}
private static String getLogClazz(String logInfo) {
return logInfo.substring(logInfo.indexOf("("), logInfo.indexOf(")") + 1);
}
private static String getLogLevel(String logInfo) {
return logInfo.substring(24, 31);
}
private static String getModule(String logInfo) {
logInfo = logInfo.substring(logInfo.indexOf("(") + 15, logInfo.length());
return logInfo.substring(0, logInfo.indexOf("."));
}
}
If you ever use this code, noticethat you will have to adjust the three methods that return the classname, log level and module name, depending on how you have named your packages, classes, modules etc..
The LOGGER.getClass().toString();
returned a string that looks something like this
[timestamp] (moduleName.packageName.src.java.yourClassName);
With the String.class() methods you can easily take the information you need.
I added a resource for a module as follows:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>nbm-maven-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<moduleType>eager</moduleType>
<nbmResources>
<nbmResource>
<directory>${basedir}/resources</directory>
<targetPath>resources</targetPath>
<includes>
<include>*.db</include>
</includes>
<excludes>
<exclude>*trace*</exclude>
</excludes>
</nbmResource>
</nbmResources>
</configuration>
</plugin>
The file shows in the Netbeans application at: target/app name/app name/resources/card_manager.mv.db. That looks fine.
Now I'm trying to get that file location as follows:
File db = InstalledFileLocator.getDefault().locate("card_manager.mv.db",
"module.codename.base", false);
But db is always null. Any idea?
Try this code...
File file = InstalledFileLocator.getDefault().locate("myfile", null, false);
if (file == null)
{
file = new File(Places.getUserDirectory() + File. separator + "myfile");
}
Or have you tried resources/card_manager.mv.db? I'm sure the application path (app name) and cluster name (second app name) is excluded from locate() but I believe you have to include resources/ path.
Modify your pom so that the card_manager.mv.db is copied to the classes folder rather than the resources folder and fetch the file from your classloader.
I have war file which I have deployed but after deploying the resources and links are not working.
<build>
<finalName>KFA</finalName>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<includes>
<include>**/*Tests.java</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
When I build the application I get kfa.war which i deploy to tomcat
but unfortunately I can't access any page, I get http status 404 -
/kfa/trainee. sample controller
#Controller
#RequestMapping("/kfa/trainee")
public class TraineeController {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
TraineeService traineeService;
RegService regService;
#Autowired
public void setTraineeService(TraineeService traineeService) {
this.traineeService = traineeService;
}
#Autowired
public void setRegService(RegService regService) {
this.regService = regService;
}
#RequestMapping(method = RequestMethod.GET)
public ModelAndView addMember(ModelMap model){
model.addAttribute("module", "kfa/trainee");
model.addAttribute("submodule", "add_trainee");
model.addAttribute("title", "Trainee");
model.addAttribute("subtitle", "Add");
model.addAttribute("trainee", new Trainee());
return new ModelAndView("/kfa/index", model);
}
}
When I ran and deploy within intellij idea I get everything working fine. My question is how should i configure the build pasted above to allow me ran the war file on tomcat in another machine.
If not understood you can ask for more information. I will be glad for your help.
If you deploy a war file called kfa.war in a tomcat container, tomcat assumes the context path /kfa if you don't give any other information while deploying.
Try to access /kfa/kfa/trainee.
But looking at the log files of your tomcat should help! You can install tomcat's manager war (https://tomcat.apache.org/tomcat-7.0-doc/manager-howto.html) to get information about the installed WARs in your container going to /manager/html.
Verify if your war has all the content that it is supposed to have by unzipping it.
If it does not have the required content make sure your project is using the right maven directory structure as mentioned here https://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html.
If not you might have to restructure your project accordingly and everything should work as expected
I was looking up how to get the application name(artifact id) and version from maven pom or manifest when I came across this question Get Maven artifact version at runtime.
The above works for me when I package the project but I can't seem to get anything to work when I try to run the program using eclipse. I tried using the .properties method when building since I assumed that is not package dependent but I am still not getting a result. If anyone has an idea or solution to this problem it would be greatly appreciated.
My last attempt is below. This uses the manifest when packaged(which works) and trying to get the .properties file when running in eclipse.
String appVersion = getClass().getPackage().getImplementationVersion();
if(appVersion == null || "".equals(appVersion)) {
appVersion = Glob.getString(appVersion);
if(appVersion == null || "".equals(appVersion)) {
System.exit(0);
}
}
Create a property file
src/main/resources/project.properties
with the below content
version=${project.version}
artifactId=${project.artifactId}
Now turn on maven resource filtering
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
so that this file is processed into
target/classes/project.properties
with some content similar to this
version=1.5
artifactId=my-artifact
Now you can read this property file to get what you want and this should work every time.
final Properties properties = new Properties();
properties.load(this.getClassLoader().getResourceAsStream("project.properties"));
System.out.println(properties.getProperty("version"));
System.out.println(properties.getProperty("artifactId"));
An easy solution with maven 4 is now to add a VersionUtil static method in your package:
package my.domain.package;
public class VersionUtil {
public static String getApplicationVersion(){
String version = VersionUtil.class.getPackage().getImplementationVersion();
return (version == null)? "unable to reach": version;
}
}
The thing is you need this ´mave-war-plugin´ in the project's pom, saying you want to add addDefaultImplementationEntries:
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
...
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
</archive>
</configuration>
</plugin>
...
Then call the VersionUtil.getApplicationVersion() from some place in your code.
I have the following plugin configuration in my maven pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>prepare-database</id>
<phase>pre-integration-test</phase>
<configuration>
<target name="run">
<java fork="false" failonerror="yes" classname="Test">
<arg line="arg1 arg2"/>
</java>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
The class is located in a package under src/main/java the package is called com.a.b and the class file is called Test.java
package com.a.b;
public class Test {
public static void main(String[] args)
{
String arg1 = args[0];
String arg2 = args[1];
doStuff(arg1, arg2);
}
public static void doStuff(String arg1, String arg2)
{
System.out.println(arg1);
}
}
When trying to execute the maven build that runs the ant task I get the following error:
An Ant BuildException has occured: Could not find Test. Make sure you
have it in your classpath
I understand that the file can not be found but I have no clue what to do about it. Any help would be highly appreciated.
Take a look at the standard-directory-layout article on the Maven site.
Source folder should be src/main/java (and not src/java/main)
Also, what exactly do you want to do with this ant target ? Do you simply need the fork ? Why can't you run it as a pure unit test, or a maven integration test and forget about the ANT target ?
H2 is well-suited for running in-memory. It only takes a couple of lines to connect to the DB and start testing, all inside the JVM, all using standard jUnit code.
Class.forName("org.h2.Driver");
Connection con = DriverManager.getConnection("jdbc:h2:mem:mytest", "sa", "");
Statement sst = con.createStatement();
sst.executeUpdate(SQL);