Maven – Quick Start

Many of my friends were facing similar kind of problem while configuring the maven, so thought to cover this topic in simple form

Disclaimer : Please consider this as a quick start guide, its not the in details one, and I tried to cover the same topic in different way.

How I look at Maven?

Maven is the tool which helps me to download/manage all required API for my project.

In old days, if you need to build a simple application which handles the MS Office files (excel, word), you have to search for the API, then on the API home page you need to go to the page which details out the all required jars to use that API, and yes few of API provider also has a ZIP file which contents all the dependent jar files, if there is any other jar dependency you need to download it from their site, and many of time you will face compilation or runtime issues as some of the jar is missing or its version is not compatible.

To fix this Maven and other build tools came into the picture, where you tell the tool the details of the repository, and the API you want to use. API provider add the details of the dependencies to use their API.

Repository : Its the server which stores the all required jar files, one of them is NEXUS, which stores the required files with their binary, source and versions. Nexus provides facility to add, publish new dependencies or jar files or any dependent files which will be used by projects. You can publish your jar files on this server so that it can be reused in other applications.

POM file : POM files has the details of the dependencies to run/use API or project. This file can also has details about project, jvm version, team members etc. POM also has the Plugins configurations, there are multiple plugins available to build, report, measure code quality, analyse dependencies and deploy.

Configuration and Getting the dependencies

Settings.xml : This file holds the configurations which is common for all Maven projects, like proxy details, repository server details, authentication details. So when you run the mvn command to build the project, maven search for the settings file in Maven Folder/conf/ and <user dir>/.m2/,  If both files exists, their contents gets merged, with the user-specific settings.xml being dominant.

Now maven know how to connect to server/internet (if required) and download the required dependencies, plugins etc.

POM.xml : In this file one can add the dependency details which looks like as

<dependency>
 <groupId>org.apache.tomcat</groupId>
 <artifactId>tomcat-jdbc</artifactId>
 <version>7.0.42</version>
 <scope>runtime</scope>
 </dependency>

GroupId, ArtifactID and version identifies the dependency uniquely, and based on these details  required file is get downloaded to .m2 directory which is your local repository, and from where the file is referred in your project.

What is SCOPE in dependency tag?

Most of the time I fund the people face problems as they havent tried to understand what this scope is for.

compile – this is the default scope, used if none is specified. Compile dependencies are available in all classpaths. Furthermore, those dependencies are propagated to dependent projects.

provided – this is much like compile, but indicates you expect the JDK or a container to provide it at runtime. It is only available on the compilation and test classpath, and is not transitive.

runtime – this scope indicates that the dependency is not required for compilation, but is for execution. It is in the runtime and test classpaths, but not the compile classpath.

test – this scope indicates that the dependency is not required for normal use of the application, and is only available for the test compilation and execution phases.

system – this scope is similar to provided except that you have to provide the JAR which contains it explicitly. The artifact is always available and is not looked up in a repository.

So based on your scope, jar or package files are referred in build process. e.g. provided and test scoped dependencies wont be added to your WAR file.

for more deatils : http://maven.apache.org/pom.html

You can exclude few of the dependencies which you wont needs to be downloaded/included from the child dependencies.

Basic commands

mvn clean install

mvn eclipse:configure-workspace
is used to add the classpath variable M2_REPO to Eclipse which points to your local repository and optional to configure other workspace features.

mvn eclipse:eclipse
generates the Eclipse configuration files.

mvn eclipse:clean
is used to delete the files used by the Eclipse IDE.

Few more commands

mvn dependency:tree -Dverbose -Dincludes=commons-collections

mvn verify

mvn dependency:analyze-only verify

mvn dependency:analyze-duplicate

mvn dependency:analyze-report

mvn site

Quick Start Guide: http://maven.apache.org/guides/getting-started/maven-in-five-minutes.html

Advertisements
Maven – Quick Start

Cross-site request and Sever configuration

While developing REST web service, we came across an error “No ‘Access-Control-Allow-Origin’ header is present on the requested resource” with Http Status code 403, after exploring more on it, found the details of CORS and how browser supports it. Obviously as a user (mostly developer) I can disable the security and can make the request, but lets understand the ideal way of handling it.

What is CORS?

This document defines a mechanism to enable client-side cross-origin requests. Specifications that enable an API to make cross-origin requests to resources can use the algorithms defined by this specification. If such an API is used on http://example.org resources, a resource on http://hello-world.example can opt in using the mechanism described by this specification (e.g., specifying Access-Control-Allow-Origin: http://example.org as response header), which would allow that resource to be fetched cross-origin from http://example.org.

You can find more details on : http://www.w3.org/TR/cors/

So if you are making request to same server but the URL is different, the request will be treated as the cross-domain, e.g. http://localhost and http://120.0.0.1 will be treated as the cross-domain. Specification is implemented by the browser to support same-origin policy and security. When browser makes a request, it check for the origin and the URL of the request made to, if it wont match (protocol+domain+port number should be same) then a pre-flight request is made to the server, which is nothing but a same request with HTTP method OPTION. e.g. if you are making a call from localhost:8080/app/index.html to 127.0.0.1:8080/app/hello then request is made to 127.0.0.1:8080/app/hello with OPTION http method.

Pre-flight Request 

OPTIONS /app/home HTTP/1.1 
Host: 127.0.0.1:8080 
Connection: keep-alive 
Cache-Control: max-age=0 
Access-Control-Request-Method: GET 
Origin: http://localhost:8080 
Access-Control-Request-Headers: accept, content-type 
Accept: */* 
Referer: http://localhost:8080/app/index.html 
  

Response

HTTP/1.1 200 OK 
Access-Control-Allow-Origin: http://localhost:8080 
Access-Control-Allow-Credentials: true 
Access-Control-Max-Age: 1800 
Access-Control-Allow-Methods: GET 
Access-Control-Allow-Headers: content-type,access-control-request-headers,access-control-request-method,accept,origin,x-requested-with 
Content-Length: 0
  

 

If your server returns the Access-Control-Allow-Origin headers then only client can access the targeted site content, when the preflight request is successful then browser makes the original request. Once the request is successful, browser cache the details of the origin, url (request made to), max-age and header details, so for subsequent requests to same URL will be served directly and in that case preflight request will be not sent.

On Server Side, How I can support the cross-site request

We do use Tomcat, from Tomact version 7.0.40 by default CorsFilter is included, you just need to enable it for your application, the minimal configuration is

	<filter>
		<filter-name>CorsFilter</filter-name>
		<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>CorsFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
 

you can specify the optional parameters by adding init parameters, follow this link for more details.

e.g.

		<init-param>
			<param-name>cors.allowed.origins</param-name>
			<param-value>http://localhost:8080, http://127.0.0.1:8080</param-value>
		</init-param>
		<init-param>
			<param-name>cors.allowed.methods</param-name>
			<param-value>GET,POST,HEAD,OPTIONS,PUT</param-value>
		</init-param>

If you have Apache or any other HTTP server between client and you application server, then make sure you have implemented cross-site support on those servers.
if your application is used or open for limited applications, it is recommended to use specific domain names list for “Allowed Origin”, if you have a global web API then you can use *.
More on OPTION method

This method allows the client to determine the options and/or requirements associated with a resource, or the capabilities of a server, without implying a resource action or initiating a resource retrieval. Mostly option do not have the body, but specification is open and in future option body may be supported to make detailed query on server.

BTW : WebSocket won’t fall under same-origin or cross-site policy, so if you create a WebSocket to different URL it will work.

Download code from GIT

Cross-site request and Sever configuration

Running Sonar Analysis Using Maven

In last post I have covered how to configure SonarQube. Let’s see how you can run a Sonar code analysis using Maven.

You need to enable sonar profile, for that you need to add following profile configuration to your settings.xml.

<id>sonar</id>
 <activation>
 <activeByDefault>true</activeByDefault>
 </activation>
 <properties>
 <sonar.jdbc.url>
 jdbc:mysql://localhost:3306/sonarqube?useUnicode=true&amp;characterEncoding=utf8&amp;rewriteBatchedStatements=true
 </sonar.jdbc.url>
 <sonar.jdbc.username>sonarUserName</sonar.jdbc.username>
 <sonar.jdbc.password>sonarPassword</sonar.jdbc.password>
 <sonar.host.url>
 http://localhost:9000
 </sonar.host.url>
 </properties>
 </profile>
   
  

you can add above code in global settings.xml, which is kept in c:\users\\.m2 folder. Or you can create a file in your parent project and while running maven command use mvn –settings settings.xml command, maven –settings option is used to provide custom setting file.

In your parent pom.xml, you can specify sonar specific properties.

<sonar.language>java</sonar.language>
<sonar.java.source>1.6</sonar.java.source>
<sonar.projectVersion>1.0</sonar.projectVersion>
<sonar.sourceEncoding>UTF-8</sonar.sourceEncoding>
<sonar.binaries>target\classes</sonar.binaries>
      

To run the SonarQube analysis run

mvn sonar:sonar

Maven will connect to the MySQL server and will run the code analysis on your code using configured rules, once the instrumentation us done, data will be persisted to MySQL server. once build is sucessfull you can access the report on your SonarQube application.

Running Sonar Analysis Using Maven