This is something that I rarely do because I use IntelliJ IDEA. Here is one of the most complex commands I issue for Maven.
mvn -P dev -DskipTests=true clean install
sheltonn February 13th, 2015
Posted In: Maven
Tags: maven, maven profiles, mvn, skip tests, skiptests
Every once in a while, you have a library that isn’t in a repository and shouldn’t be there for some reason. We had such a library. How do you use that library when it is on your local system instead of in a repository? Use the system scope.
<dependency> <groupId>com.this.and.that</groupId> <artifactId>non-repo-library</artifactId> <version>1.0</version> <scope>system</scope> <systemPath>/my/path/to/lib.jar</systemPath> </dependency>
System scope tells Maven that the dependency is on the file system. System Path tells Maven where to find the dependency.
sheltonn December 10th, 2014
Posted In: Maven
Tags: dependency, maven, scope, system, systempath
We were given a project that built a custom server. They had the need to deploy the code and the dependencies. The dependencies were placed in /lib via the maven-dependency-plugin. They were generating the MANIFEST.MF via the maven-jar-plugin. The problem was that what was in the manifest wasn’t exactly what was in the lib directory. An example is in the lib directory, there was a file named adapter-models-1.0-SNAPSHOT.jar. Unfortunately, the manifest contained adapter-models-1.0-20141201.182800-510.jar in the Class-Path, which was the unique snapshot identifier.
I fixed this by adding useUniqueVersions to their manifest element of the maven-jar-plugin.
<plugin> <artifactId>maven-jar-plugin</artifactId> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <classpathPrefix>lib/</classpathPrefix> <mainClass>com.this.and.that</mainClass> <useUniqueVersions>false</useUniqueVersions> </manifest> <manifestEntries> <Implementation-Version>${project.version}-${changeSet:} (${changeSetDate:}) </Implementation-Version> </manifestEntries> </archive> </configuration> </plugin>
sheltonn December 1st, 2014
Posted In: Maven
Tags: manifest, maven, maven maven-jar-plugin snapshot, maven-jar-plugin, snapshot
The benefit of having a local Maven repository is that only one developer suffers the delay of the network traffic requests to repo1. If you have a local maven repository and your developers have mirrors setup in their settings.xml
<?xml version="1.0" encoding="UTF-8"?> <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> <mirrors> <mirror> <id>artifactory</id> <mirrorOf>*</mirrorOf> <url>http://artifactory.cdinteractive.com:8080/artifactory/repo</url> <name>Artifactory</name> </mirror> </mirrors> </settings>
sheltonn March 3rd, 2014
Posted In: Maven
Tags: artifactory, dependencies, maven, mirror, mirroring, mirrors
Springframework MVC 3.2 introduced the ability to test controllers via MockMVC. In this example, we will test a controller that returns JSON via @ResponseBody.
Here are the dependencies that you will need.
<!-- This is usually included as part of your normal dependencies. If not, include this way --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>1.9.5</version> <scope>test</scope> </dependency> <dependency> <groupId>com.jayway.jsonpath</groupId> <artifactId>json-path</artifactId> <version>${jsonpath.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>com.jayway.jsonpath</groupId> <artifactId>json-path-assert</artifactId> <version>${jsonpath.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency>
This is an example of the spring context.
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <mvc:annotation-driven/> <context:component-scan base-package="com.cdi.igs.core.spring.web"/> </beans>
The basic test class needs to have the following annotations, properties and setup defined. Please note the static imports. You want to use these from the mock mvc request builders.
import https://javaninja.net/files/tag/com.fasterxml.jackson.databind.objectmapper; import https://javaninja.net/files/tag/org.junit.assert; import https://javaninja.net/files/tag/org.junit.before; import https://javaninja.net/files/tag/org.junit.test; import https://javaninja.net/files/tag/org.junit.runner.runwith; import https://javaninja.net/files/tag/org.springframework.beans.factory.annotation.autowired; import https://javaninja.net/files/tag/org.springframework.http.mediatype; import https://javaninja.net/files/tag/org.springframework.test.context.contextconfiguration; import https://javaninja.net/files/tag/org.springframework.test.context.junit4.springjunit4classrunner; import https://javaninja.net/files/tag/org.springframework.test.context.web.webappconfiguration; import https://javaninja.net/files/tag/org.springframework.test.web.servlet.mockmvc; import https://javaninja.net/files/tag/org.springframework.test.web.servlet.setup.mockmvcbuilders; import https://javaninja.net/files/tag/org.springframework.web.context.webapplicationcontext; import https://javaninja.net/files/tag/static org.hamcrest.matchers.*; import https://javaninja.net/files/tag/static org.springframework.test.web.servlet.request.mockmvcrequestbuilders.post; import https://javaninja.net/files/tag/static org.springframework.test.web.servlet.result.mockmvcresulthandlers.print; import https://javaninja.net/files/tag/static org.springframework.test.web.servlet.result.mockmvcresultmatchers.jsonpath; import https://javaninja.net/files/tag/static org.springframework.test.web.servlet.result.mockmvcresultmatchers.status; @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextConfiguration public class TestGlobalControllerExceptionHandler { @Autowired private WebApplicationContext wac; private MockMvc mockMvc; @Before public void setup() { mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); } //... }
This is an example test method that calls a spring controller that returns a string. We are creating an empty model object that we convert to JSON. We tell the method that we are calling that we are sending JSON, because the method that we are calling expects to be sent a JSON object. We get validation errors in this case, that we compare with our expected results. The JSON response that we get back from the call to the controller is “{“fieldErrors”:[{“message”:”may not be null”},{“message”:”may not be null”}]}”
@Test public void testMyMethod() throws Exception { mockMvc.perform(post("/mymethod") .content(new ObjectMapper().writeValueAsString(new TargetExceptionModel())) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isBadRequest()) .andExpect(jsonPath("$.fieldErrors", hasSize(2))) .andExpect(jsonPath("$.fieldErrors[*].message", contains("may not be null", "may not be null"))) .andDo(print()); }
Here is an example of a controller test method that users other types of matchers. Example data is:
{"status":"SUCCESS","message":null,"previousPage":null,"nextPage":"login/privacy_policy","errors":null,"exception":null,"idSetting":"pri","setting":"privacy-Starfish","value":"test","settingText":"lots and lots of text","date":"01-27-2014"}
@Test public void testGetPrivacyByClientSuccess() throws Exception { mockMvc.perform(get("/privacy/pri")) .andExpect(status().isOk()) .andExpect(jsonPath("$.idSetting", containsString("pri"))) .andExpect(jsonPath("$.setting", containsString("privacy-Starfish"))) .andExpect(jsonPath("$.settingText", notNullValue())) .andExpect(jsonPath("$.value", containsString("test"))) .andExpect(jsonPath("$.exception", nullValue())) .andDo(print()); }
I needed to write a method that passed an object that contained an exception object back to the calling method. The data being sent back was:
{"status":"ERROR","message":null,"previousPage":null,"nextPage":null,"errors":null,"exception":{"cause":null,"stackTrace":[{"methodName":"copyProperties","fileName":"PropertyUtilsBean.java","lineNumber":276,"className":"org.apache.commons.beanutils.PropertyUtilsBean","nativeMethod":false},{"methodName":"copyProperties","fileName":"PropertyUtils.java","lineNumber":219,"className":"org.apache.commons.beanutils.PropertyUtils","nativeMethod":false},{"methodName":"getPrivacy","fileName":"LoginService.java","lineNumber":193,"className":"com.cdi.igs.core.login.LoginService","nativeMethod":false},{"methodName":"getPrivacyByClient","fileName":"LoginController.java","lineNumber":94,"className":"com.cdi.igs.services.LoginController","nativeMethod":false},{"methodName":"invoke0","fileName":"NativeMethodAccessorImpl.java","lineNumber":-2,"className":"sun.reflect.NativeMethodAccessorImpl","nativeMethod":true},{"methodName":"invoke","fileName":"NativeMethodAccessorImpl.java","lineNumber":57,"className":"sun.reflect.NativeMethodAccessorImpl","nativeMethod":false},{"methodName":"invoke","fileName":"DelegatingMethodAccessorImpl.java","lineNumber":43,"className":"sun.reflect.DelegatingMethodAccessorImpl","nativeMethod":false},{"methodName":"invoke","fileName":"Method.java","lineNumber":606,"className":"java.lang.reflect.Method","nativeMethod":false},{"methodName":"invoke","fileName":"InvocableHandlerMethod.java","lineNumber":214,"className":"org.springframework.web.method.support.InvocableHandlerMethod","nativeMethod":false},{"methodName":"invokeForRequest","fileName":"InvocableHandlerMethod.java","lineNumber":132,"className":"org.springframework.web.method.support.InvocableHandlerMethod","nativeMethod":false},{"methodName":"invokeAndHandle","fileName":"ServletInvocableHandlerMethod.java","lineNumber":104,"className":"org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod","nativeMethod":false},{"methodName":"invokeHandleMethod","fileName":"RequestMappingHandlerAdapter.java","lineNumber":749,"className":"org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter","nativeMethod":false},{"methodName":"handleInternal","fileName":"RequestMappingHandlerAdapter.java","lineNumber":690,"className":"org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter","nativeMethod":false},{"methodName":"handle","fileName":"AbstractHandlerMethodAdapter.java","lineNumber":83,"className":"org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter","nativeMethod":false},{"methodName":"doDispatch","fileName":"DispatcherServlet.java","lineNumber":945,"className":"org.springframework.web.servlet.DispatcherServlet","nativeMethod":false},{"methodName":"doService","fileName":"DispatcherServlet.java","lineNumber":876,"className":"org.springframework.web.servlet.DispatcherServlet","nativeMethod":false},{"methodName":"processRequest","fileName":"FrameworkServlet.java","lineNumber":961,"className":"org.springframework.web.servlet.FrameworkServlet","nativeMethod":false},{"methodName":"doGet","fileName":"FrameworkServlet.java","lineNumber":852,"className":"org.springframework.web.servlet.FrameworkServlet","nativeMethod":false},{"methodName":"service","fileName":"HttpServlet.java","lineNumber":687,"className":"javax.servlet.http.HttpServlet","nativeMethod":false},{"methodName":"service","fileName":"FrameworkServlet.java","lineNumber":837,"className":"org.springframework.web.servlet.FrameworkServlet","nativeMethod":false},{"methodName":"service","fileName":"TestDispatcherServlet.java","lineNumber":64,"className":"org.springframework.test.web.servlet.TestDispatcherServlet","nativeMethod":false},{"methodName":"service","fileName":"HttpServlet.java","lineNumber":790,"className":"javax.servlet.http.HttpServlet","nativeMethod":false},{"methodName":"doFilter","fileName":"MockFilterChain.java","lineNumber":170,"className":"org.springframework.mock.web.MockFilterChain$ServletFilterProxy","nativeMethod":false},{"methodName":"doFilter","fileName":"MockFilterChain.java","lineNumber":137,"className":"org.springframework.mock.web.MockFilterChain","nativeMethod":false},{"methodName":"perform","fileName":"MockMvc.java","lineNumber":141,"className":"https://javaninja.net/files/tag/org.springframework.test.web.servlet.mockmvc","nativeMethod":false},{"methodName":"testGetPrivacyByClientFail","fileName":"TestLoginController.java","lineNumber":96,"className":"com.cdi.igs.services.TestLoginController","nativeMethod":false},{"methodName":"invoke0","fileName":"NativeMethodAccessorImpl.java","lineNumber":-2,"className":"sun.reflect.NativeMethodAccessorImpl","nativeMethod":true},{"methodName":"invoke","fileName":"NativeMethodAccessorImpl.java","lineNumber":57,"className":"sun.reflect.NativeMethodAccessorImpl","nativeMethod":false},{"methodName":"invoke","fileName":"DelegatingMethodAccessorImpl.java","lineNumber":43,"className":"sun.reflect.DelegatingMethodAccessorImpl","nativeMethod":false},{"methodName":"invoke","fileName":"Method.java","lineNumber":606,"className":"java.lang.reflect.Method","nativeMethod":false},{"methodName":"runReflectiveCall","fileName":"FrameworkMethod.java","lineNumber":47,"className":"org.junit.runners.model.FrameworkMethod$1","nativeMethod":false},{"methodName":"run","fileName":"ReflectiveCallable.java","lineNumber":12,"className":"org.junit.internal.runners.model.ReflectiveCallable","nativeMethod":false},{"methodName":"invokeExplosively","fileName":"FrameworkMethod.java","lineNumber":44,"className":"org.junit.runners.model.FrameworkMethod","nativeMethod":false},{"methodName":"evaluate","fileName":"InvokeMethod.java","lineNumber":17,"className":"org.junit.internal.runners.statements.InvokeMethod","nativeMethod":false},{"methodName":"evaluate","fileName":"RunBefores.java","lineNumber":26,"className":"org.junit.internal.runners.statements.RunBefores","nativeMethod":false},{"methodName":"evaluate","fileName":"RunBeforeTestMethodCallbacks.java","lineNumber":74,"className":"org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks","nativeMethod":false},{"methodName":"evaluate","fileName":"RunAfterTestMethodCallbacks.java","lineNumber":83,"className":"org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks","nativeMethod":false},{"methodName":"evaluate","fileName":"SpringRepeat.java","lineNumber":72,"className":"org.springframework.test.context.junit4.statements.SpringRepeat","nativeMethod":false},{"methodName":"runChild","fileName":"SpringJUnit4ClassRunner.java","lineNumber":232,"className":"https://javaninja.net/files/tag/org.springframework.test.context.junit4.springjunit4classrunner","nativeMethod":false},{"methodName":"runChild","fileName":"SpringJUnit4ClassRunner.java","lineNumber":89,"className":"https://javaninja.net/files/tag/org.springframework.test.context.junit4.springjunit4classrunner","nativeMethod":false},{"methodName":"run","fileName":"ParentRunner.java","lineNumber":238,"className":"org.junit.runners.ParentRunner$3","nativeMethod":false},{"methodName":"schedule","fileName":"ParentRunner.java","lineNumber":63,"className":"org.junit.runners.ParentRunner$1","nativeMethod":false},{"methodName":"runChildren","fileName":"ParentRunner.java","lineNumber":236,"className":"org.junit.runners.ParentRunner","nativeMethod":false},{"methodName":"access$000","fileName":"ParentRunner.java","lineNumber":53,"className":"org.junit.runners.ParentRunner","nativeMethod":false},{"methodName":"evaluate","fileName":"ParentRunner.java","lineNumber":229,"className":"org.junit.runners.ParentRunner$2","nativeMethod":false},{"methodName":"evaluate","fileName":"RunBeforeTestClassCallbacks.java","lineNumber":61,"className":"org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks","nativeMethod":false},{"methodName":"evaluate","fileName":"RunAfterTestClassCallbacks.java","lineNumber":71,"className":"org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks","nativeMethod":false},{"methodName":"run","fileName":"ParentRunner.java","lineNumber":309,"className":"org.junit.runners.ParentRunner","nativeMethod":false},{"methodName":"run","fileName":"SpringJUnit4ClassRunner.java","lineNumber":175,"className":"https://javaninja.net/files/tag/org.springframework.test.context.junit4.springjunit4classrunner","nativeMethod":false},{"methodName":"run","fileName":"JUnitCore.java","lineNumber":160,"className":"org.junit.runner.JUnitCore","nativeMethod":false},{"methodName":"startRunnerWithArgs","fileName":"JUnit4IdeaTestRunner.java","lineNumber":74,"className":"com.intellij.junit4.JUnit4IdeaTestRunner","nativeMethod":false},{"methodName":"prepareStreamsAndStart","fileName":"JUnitStarter.java","lineNumber":211,"className":"com.intellij.rt.execution.junit.JUnitStarter","nativeMethod":false},{"methodName":"main","fileName":"JUnitStarter.java","lineNumber":67,"className":"com.intellij.rt.execution.junit.JUnitStarter","nativeMethod":false},{"methodName":"invoke0","fileName":"NativeMethodAccessorImpl.java","lineNumber":-2,"className":"sun.reflect.NativeMethodAccessorImpl","nativeMethod":true},{"methodName":"invoke","fileName":"NativeMethodAccessorImpl.java","lineNumber":57,"className":"sun.reflect.NativeMethodAccessorImpl","nativeMethod":false},{"methodName":"invoke","fileName":"DelegatingMethodAccessorImpl.java","lineNumber":43,"className":"sun.reflect.DelegatingMethodAccessorImpl","nativeMethod":false},{"methodName":"invoke","fileName":"Method.java","lineNumber":606,"className":"java.lang.reflect.Method","nativeMethod":false},{"methodName":"main","fileName":"AppMain.java","lineNumber":120,"className":"com.intellij.rt.execution.application.AppMain","nativeMethod":false}],"message":"No origin bean specified","localizedMessage":"No origin bean specified","suppressed":[]},"idSetting":"Starfish1","setting":null,"value":null,"settingText":null,"date":null}
@Test public void testGetPrivacyByClientFail() throws Exception { mockMvc.perform(get("/privacy/Starfish1")) .andExpect(status().isOk()) .andExpect(jsonPath("$.idSetting", containsString("Starfish1"))) .andExpect(jsonPath("$.setting", nullValue())) .andExpect(jsonPath("$.settingText", nullValue())) .andExpect(jsonPath("$.value", nullValue())) .andExpect(jsonPath("$.exception.cause", nullValue())) .andExpect(jsonPath("$.exception.stackTrace", notNullValue())) .andExpect(jsonPath("$.exception.stackTrace[0].methodName", notNullValue())) .andDo(print()); }
To get the content and store it in a variable outside the test, add .andReturn() to the end of the perform and store the result in a MvcResult, then get the content.
MvcResult result = mockMvc.perform(post("/login") .content( "{"userName":"screen011","password":"Jason3080!"," + ""remoteAddress":"0.0" + ".0.0"}" ) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$.exception", nullValue())) .andExpect(jsonPath("$.errors", hasSize(0))) .andExpect((jsonPath("$.ssoToken", notNullValue()))) .andDo(print()) .andReturn(); String content = result.getResponse().getContentAsString();
Then if you need to extract a value out of the JSON, you can use JsonPath out of jayway like
String content = result.getResponse().getContentAsString(); assertNotNull(content); String ssoToken = JsonPath.read(content, "$.ssoToken"); assertNotNull(ssoToken);
sheltonn February 27th, 2014
Posted In: Java, MockMVC, Spring, Spring MVC
Tags: Annotation, Java, maven, mockito, mockmvc, programming, Spring, spring mvc
mvn versions:display-dependency-updates
The output is useful, but you still need to interpret it. In this case, there is a beta library that is suggested. Not.
INFO] ------------------------------------------------------------------------ [INFO] Building igs 1.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- versions-maven-plugin:2.1:display-dependency-updates (default-cli) @ igs --- [INFO] The following dependencies in Dependency Management have newer versions: [INFO] commons-collections:commons-collections ............ 3.2.1 -> 20040616 [INFO] org.hibernate:hibernate-validator ......... 5.0.1.Final -> 5.1.0.Beta1 [INFO] [INFO]
In this case, a library with a version number that doesn’t follow the normal version patters is mistakenly noted as a newer version.
[INFO] ------------------------------------------------------------------------ [INFO] Building assets 1.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- versions-maven-plugin:2.1:display-dependency-updates (default-cli) @ assets --- [INFO] The following dependencies in Dependency Management have newer versions: [INFO] commons-collections:commons-collections ............ 3.2.1 -> 20040616 [INFO] org.hibernate:hibernate-validator ......... 5.0.1.Final -> 5.1.0.Beta1 [INFO] [INFO]
sheltonn February 7th, 2014
Posted In: Maven
Tags: dependencies, maven, maven dependencies, maven plugins, plugins
I never really understood the use of the bundleFileName in the maven-ear-plugin. Who looks inside the .ear anyway. Well, there is a reason it is there.
I had to set the finalName property in the build section of several Maven modules across several projects. I learned the hard way that Maven modules do not talk to each other. The maven-ear-plugin assumes that the name of the artifacts is the default name. If you use finalName to change the name of the artifact, it is not aware. It configures your ear, but the file that it points to for the ejb or war module will not be there. Doh!
Example of finalName usage in an ejb module:
<build> <finalName>isgwebsupport</finalName> <plugins> <plugin> <artifactId>maven-ejb-plugin</artifactId> <version>2.3</version> <configuration> <ejbVersion>3.0</ejbVersion> <generateClient>true</generateClient> <archive> <manifest> <addClasspath>true</addClasspath> <classpathPrefix>lib/</classpathPrefix> </manifest> </archive> </configuration> </plugin> </plugins> </build>
Example of finalName usage in a war module:
<build> <finalName>isgwebsupport</finalName> <plugins> <plugin> <artifactId>maven-war-plugin</artifactId> <version>2.3</version> <configuration> <!-- Needed for skinny war http://maven.apache.org/plugins/maven-war-plugin/examples/skinny-wars.html --> <packagingExcludes>WEB-INF/lib/*.jar</packagingExcludes> <archive> <manifest> <addClasspath>true</addClasspath> <classpathPrefix>lib/</classpathPrefix> </manifest> </archive> </configuration> </plugin> </plugins> </build>
So, if you set the finalName of an ejb module or a web module, you must also set the bundleFileName in the ear module.
NOTE: You must specify the file extension when you use bundleFileName.
Example of the usage of bundleFileName in an ear module:
<build> <finalName>isgwebsupport</finalName> <plugins> <plugin> <artifactId>maven-ear-plugin</artifactId> <version>2.7</version> <configuration> <version>5</version> <description>ISGWebSupport</description> <displayName>ISGWebSupport</displayName> <defaultLibBundleDir>/lib</defaultLibBundleDir> <skinnyWars>true</skinnyWars> <modules> <webModule> <groupId>${project.groupId}</groupId> <artifactId>websupport-war</artifactId> <contextRoot>/giswebsupport</contextRoot> <bundleFileName>isgwebsupport.war</bundleFileName> </webModule> <ejbModule> <groupId>${project.groupId}</groupId> <artifactId>websupport-ejb</artifactId> <bundleFileName>isgwebsupport.jar</bundleFileName> </ejbModule> </modules> </configuration> </plugin> </plugins> </build>
Lesson learned.
sheltonn January 18th, 2013
Posted In: Maven
Tags: build, bundleFileName, ear, ejbModule, finalName, J2ee, JEE, maven, maven-ear-plugin, plugin, webModule
You would think that this would be terribly easy, but it isn’t. It took several attempts before I figured out what they wanted. Too bad their contextual help doesn’t give you the details.
Select the “Deploy” tab from the top, then select the “Artifacts Bundle” tab from the left. Choose the file you want, then hit deploy.
The tricky part is that they expect very specific things from the file. In my case, I was trying to import the artifact corresponding to
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjtools</artifactId> <version>1.6.11</version> </dependency>
What they don’t tell you is that the name of the file will be part of the groupId. So I ended up with an archive named org.zip. The contents of the archive were:
/aspectj
/aspectjtools
/1.6.11
aspectjtools-1.6.11.jar
aspectjtools-1.6.11.jar.sha1
aspectjtools-1.6.11.pom
aspectjtools-1.6.11.pom.sha1
In hindsight, I might have been able to name the archive org.aspectj.aspectjtools, then inside I could have multiple version directories, each containing their respective artifacts.
sheltonn January 17th, 2013
Posted In: Maven
Tags: artifact, artifactory, bundle, dependency, maven
Maven EJB MODULES
EJB modules are just like normal, but they also have an manifest section:
<build> <plugins> <plugin> <artifactId>maven-ejb-plugin</artifactId> <version>2.3</version> <configuration> <ejbVersion>3.0</ejbVersion> <generateClient>true</generateClient> <archive> <manifest> <addClasspath>true</addClasspath> <classpathPrefix>lib/</classpathPrefix> </manifest> </archive> </configuration> </plugin> </plugins> </build>
MAVEN WEB MODULES
Do everything like you normally would, except you will need a build section like the following:
<build> <plugins> <plugin> <!-- Needed for skinny war http://maven.apache.org/plugins/maven-war-plugin/examples/skinny-wars.html --> <artifactId>maven-war-plugin</artifactId> <version>2.3</version> <configuration> <packagingExcludes>WEB-INF/lib/*.jar</packagingExcludes> <archive> <manifest> <addClasspath>true</addClasspath> <classpathPrefix>lib/</classpathPrefix> </manifest> </archive> </configuration> </plugin> </plugins> </build>
MAVEN EAR MODULE
<?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> <parent> <groupId>com.appriss.justicexchange.licensemgr</groupId> <artifactId>licensemgr-parent</artifactId> <version>3.0-SNAPSHOT</version> </parent> <artifactId>licensemgr-ear</artifactId> <packaging>ear</packaging> <dependencies> <dependency> <groupId>${project.groupId}</groupId> <artifactId>licensemgr-ejb</artifactId> <version>${project.version}</version> <type>ejb</type> </dependency> <dependency> <groupId>${project.groupId}</groupId> <artifactId>licensemgr-war</artifactId> <version>${project.version}</version> <type>war</type> </dependency> <!-- Also include the war as a type=pom so that it pulls in the dependencies for inclusion in the ear /lib. --> <dependency> <groupId>${project.groupId}</groupId> <artifactId>licensemgr-war</artifactId> <version>${project.version}</version> <type>pom</type> </dependency> </dependencies> <build> <finalName>licensemgr-${project.version}</finalName> <plugins> <plugin> <artifactId>maven-ear-plugin</artifactId> <version>2.7</version> <configuration> <version>5</version> <displayName>ISG License Manager Application</displayName> <description>LicenseManager</description> <defaultLibBundleDir>/lib</defaultLibBundleDir> <skinnyWars>true</skinnyWars> <modules> <ejbModule> <groupId>${project.groupId}</groupId> <artifactId>licensemgr-ejb</artifactId> </ejbModule> <webModule> <groupId>${project.groupId}</groupId> <artifactId>licensemgr-war</artifactId> <contextRoot>licensemgr</contextRoot> <bundleFileName>licensemgr-${project.version}.war</bundleFileName> </webModule> </modules> </configuration> </plugin> </plugins> </build> </project>
There should normally be a dependency entry for each module that will be packaged into the war. The EJB modules will be included with a of ejb and the WAR modules will be included with a of war. You ALSO need to add an extra dependency for each WAR module with a of pom. This will cause all of the dependencies to be pulled into the ear module and placed in the library bundle directory (/lib). If you don’t do this, you will need to duplicate each dependency of each war module as a dependency of the ear module.
The build section has 2 entries related to skinny wars:
sheltonn January 4th, 2013
Tags: computer, ear, ejb, maven, skinny wars, war, web modules
Maven is geared around the concept of producing one artifact per Maven module. If you need to have a Maven module produce multiple artifacts, you can use the Maven Assembly plugin to accomplish your goals. If you need the maven assembly plugin to produce two artifacts, it must be with two separate execution blocks. One execution block creates one artifact, like one module typically produces one artifact.
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>2.3</version> <executions> <execution> <id>client</id> <phase>package</phase> <goals> <goal>single</goal> </goals> <configuration> <finalName>${project.artifactId}-${project.version}</finalName> <appendAssemblyId>true</appendAssemblyId> <descriptors> <descriptor>src/main/assembly/client.xml</descriptor> </descriptors> </configuration> </execution> <execution> <!-- NOTE This is for backwards compatibility with the original builds--> <id>client-no-version</id> <phase>package</phase> <goals> <goal>single</goal> </goals> <configuration> <finalName>licensemgr-3.0-client</finalName> <appendAssemblyId>false</appendAssemblyId> <descriptors> <descriptor>src/main/assembly/client.xml</descriptor> </descriptors> </configuration> </execution> </executions> </plugin>
sheltonn June 12th, 2012
Posted In: Maven