понедельник, 14 марта 2011 г.

 

How to edit maven Super POM

Sometimes you want to move some common information from the maven project to one place. But you don't want to create a parent POM for all your projects (maybe because of versioning problems - each child project must know exact version of parent project).

The example of such common information is <distributionManagement> section that can't be place at settings.xml as we know. Hovewer, the is a thing that can help us - it's called maven Super POM. Good article about Maven POM and Super POM could be found here.

To put some information into the Super POM you should edit file ${M2_HOME}/lib/maven-2.1.0-uber.jar/org/apache/maven/project/pom-4.0.0.xml (here I use maven-2.1.0, so change path according to your version).

You can place your section of distribution management right after <name> section like that:

<project>
<modelVersion>4.0.0</modelVersion>
<name>Maven Default Project</name>

<distributionManagement>
<repository>
<id>depser</id>
<name>ext-releases</name>
<url>http://artifactory.example.com:8081/artifactory/ext-releases</url>
</repository>
<snapshotRepository>
<id>depser</id>
<name>ext-snapshots</name>
<url>http://artifactory.example.com:8081/artifactory/ext-snapshots</url>
</snapshotRepository>
</distributionManagement>

<repositories>
<repository>
<id>central</id>
<name>Maven Repository Switchboard</name>
<layout>default</layout>
<url>http://repo1.maven.org/maven2</url>


...


Now you can remove this section from yout project POM files and test the result with mvn deploy command

Ярлыки:


понедельник, 25 января 2010 г.

 

Deep pretty-printing in Java

Sometimes I need to insert debug logging into the code to breifly look into input or output parameters of some service (says EJB). If object, I want to look, has a big aggregation hierarchy It may take a long way to start debugger and manually expand all the leafs of a tree that represents this object. The good solution here is to make some aspest (Interceptor in EJB terms) that print input and output of a service.

Apache has a library for pretty-printing objects inside commons-lang. So the easiest way is just to write out :



import org.apache.commons.lang.builder.ReflectionToStringBuilder;
//...
String s = ReflectionToStringBuilder.toString(param);
System.out.println(s);


It's very quick and helpful when you need to print java-bean with lots of primitive field. But if hierarchy has more then one level, we need to dig deeper. I found quite a good solution based on inheriring org.apache.commons.lang.builder.ToStringStyle.
So that is it:


public class MyToStringStyle extends ToStringStyle {
int offset;

public MyToStringStyle () {
this(0);
}

private MyToStringStyle (int offset) {
this.offset = offset;
String off = "";
for (int i=0; i < offset; i++) off += " ";
this.setContentStart("[");
this.setFieldSeparator(SystemUtils.LINE_SEPARATOR + off + " ");
this.setFieldSeparatorAtStart(true);
this.setContentEnd(SystemUtils.LINE_SEPARATOR + off + "]");
}

protected void appendDetail(StringBuffer buffer, String fieldName, Collection col) {
buffer.append('[');
for (Object o: col) {
buffer.append(ReflectionToStringBuilder.toString(o, new MyToStringStyle(offset + 1)));
buffer.append(',');
}
if (buffer.charAt(buffer.length()-1) == ',') buffer.setCharAt(buffer.length()-1, ']');
}

protected void appendDetail(StringBuffer buffer, String fieldName, Object value) {
if (value.getClass().getName().startsWith("com.my.package")) {
buffer.append(ReflectionToStringBuilder.toString(value, new MyToStringStyle(offset + 1)));
} else {
super.appendDetail(buffer, fieldName, value);
}

}
}


As you can see here I've got a filter for going deeper - we only do it if class belong to our package com.my.package, but you can replace the filter's logic by your need. Another consideration is that this code will work for tree-like and DAG-like hierarchies but not for graphes with cycles. You can improve algorythm by introdusing HashSet of all visited graph nodes. So, when you meet node second time, just do nothing (or print backreference to it).

Oh, almost forgot! This is how to use a new class:


String s = ReflectionToStringBuilder.toString(value, new MyToStringStyle()));
System.out.println(s);

Ярлыки:


понедельник, 2 марта 2009 г.

 

Testing Embedded Glassfish b10

Embedded Glassfish for Unit Test is much closer to "real world" than Jetty. EJB, JMS and JTA simply don't work on lightweight Web Containers. I tried it in maven project and get success after some troubles. Here is my configuration.

Maven repositories:

<repositories>
<repository>
<id>gfe</id>
<url>http://maven.glassfish.org/content/groups/glassfish/</url>
</repository>
</repositories>




and dependency:

<dependency>
<groupId>org.glassfish.embedded</groupId>
<artifactId>glassfish-embedded-all</artifactId>
<version>3.0-Prelude-Embedded-b10</version>
</dependency>



If you use Hibernate you should do some hack with its dependencies because asm's versions conflict:

<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>3.2.6.ga</version>
<exclusions>
<exclusion>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
</exclusion>
<exclusion>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
<version>3.1</version>
</dependency>





Now we ready to write some code:


// Starting web container
EmbeddedInfo info = new EmbeddedInfo();
info.setServerName("GF Embed");
info.setHttpPort(gfPort);
info.setVerbose(true);
info.setLogging(true);
gfServer = new Server(info);
gfServer.start();

Properties prop = new Properties();
//Setting datasource
prop.setProperty("DEFAULT", "src/main/resources/datasource/SSO_DataSources.xml");

//Here we need to copy resource dtd file, because somewhy embedded glassfish hasn't it
File dtdDir = new File("gfe/lib/dtds");
dtdDir.mkdirs();
String dtdFile = "sun-resources_1_3.dtd";
FileUtils.copy(new File(dtdFile), new File(dtdDir, dtdFile));

gfServer.getCommandExecutor().execute("add-resources", prop);
System.out.println("Hello");

//Deploying war-file here
gfServer.getDeployer().deploy(new File("target/card-service-web-1.05.009.war"));

//... DO SOME WORK
gfServer.stop();




Almost all. One bad thing is that we must use certain version of application descriptors. I coudn't figure what sun-web.xml must be (so I kicked it off) but web.xml must contain such header:


<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:j2ee="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.4"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">





That's it. Enjoy full functionality of efficient webserver in a single JVM.

Ярлыки:


пятница, 19 декабря 2008 г.

 

Blogger's code snippets intergrarion

I needed to insert some code snippets into blogs. Searching in internet I found such interesting resources and posts:

  1. http://developertips.blogspot.com/2007/08/syntaxhighlighter-on-blogger.html


  2. Another blog record


  3. Most correct blog record


  4. http://code.google.com/p/syntaxhighlighter/




In the 3rd link author forgot to add
dp.SyntaxHighlighter.BloggerMode();

So, what we really need to do is to add two records into Blogger's Layout -> Change HTML:


  1. Before </head>

    <link href="http://mortenlyhr.googlecode.com/svn/trunk/SyntaxHighlighter/Styles/SyntaxHighlighter.css" type="text/css" rel="stylesheet" />
    <script language="javascript" src="http://mortenlyhr.googlecode.com/svn/trunk/SyntaxHighlighter/Scripts/shCore.js"></script>
    <script language="javascript" src="http://mortenlyhr.googlecode.com/svn/trunk/SyntaxHighlighter/Scripts/shBrushCSharp.js"></script>
    <script language="javascript" src="http://mortenlyhr.googlecode.com/svn/trunk/SyntaxHighlighter/Scripts/shBrushXml.js"></script>
    <script language="javascript" src="http://mortenlyhr.googlecode.com/svn/trunk/SyntaxHighlighter/Scripts/shBrushCss.js"></script>
    <script language="javascript" src="http://mortenlyhr.googlecode.com/svn/trunk/SyntaxHighlighter/Scripts/shBrushJScript.js"></script>
    <script language="javascript" src="http://mortenlyhr.googlecode.com/svn/trunk/SyntaxHighlighter/Scripts/shBrushJava.js"></script>
    <script language="javascript" src="http://mortenlyhr.googlecode.com/svn/trunk/SyntaxHighlighter/Scripts/shBrushSql.js"></script>



  2. Before </body>

    <script language="javascript">
    dp.SyntaxHighlighter.ClipboardSwf = 'http://mortenlyhr.googlecode.com/svn/trunk/SyntaxHighlighter/Scripts/clipboard.swf';
    dp.SyntaxHighlighter.BloggerMode();
    dp.SyntaxHighlighter.HighlightAll('code');
    </script>




I don't know why but in my Firefox 3.0.4 it does realy matter to use <script> </script> instead of <script/>.

Now we can bravely insert our code into <pre> tags. Like

<pre name="code" class="Java">
Java code
</pre>


or


<pre name="code" class="Xml">
Xml code
</pre>


Just don't forget to replace all < in your code by &lt;

Ярлыки:


четверг, 18 декабря 2008 г.

 

Embedded LDAP

Today, I've tried to setup some embedded LDAP server for my automated integration testing. First of all, since my language is java, I need pure Java Ldap Server implementation. There are two main alternatives: Apache DS and OpenDS.
Some guys from Inter LDAP declared that Apache DS is better, but they've choosen Open LDAP because it support some not-frequently-used-feature like extended control. I had no intention to use advanced feaures, so I've choosen Apache DS because it had better documentation, set of plugins for eclipse and (the main reason) I've used it before as standalone server.

First of all, I've read some blogs from Apache DS team:

  1. http://cwiki.apache.org/DIRxSRVx11/42-using-apacheds-for-unit-tests.html

  2. http://directory.apache.org/apacheds/1.0/embedding-apacheds-as-a-web-application.html

  3. http://cwiki.apache.org/DIRxSRVx11/41-embedding-apacheds-into-an-application.html



The compilation of blogs above released into folowing embeddable server code:


import java.io.File;
import java.util.HashSet;

import org.apache.directory.server.core.*;
import org.apache.directory.server.core.entry.ServerEntry;
import org.apache.directory.server.core.partition.Partition;
import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmIndex;
import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmPartition;
import org.apache.directory.server.ldap.LdapService;
import org.apache.directory.server.protocol.shared.SocketAcceptor;
import org.apache.directory.server.protocol.shared.store.LdifFileLoader;
import org.apache.directory.server.xdbm.Index;

public class ApacheLDAPServer {

private LdapService ldapService;
private DirectoryService directoryService;
private Partition partition;
int port = 9389;

private static ApacheLDAPServer instance;

public static ApacheLDAPServer getInstance() {
if (instance == null) {
instance = new ApacheLDAPServer();
}
return instance;
}

private ApacheLDAPServer() {
}


public void start() throws Exception {
directoryService = new DefaultDirectoryService();
directoryService.setAllowAnonymousAccess(true);
directoryService.setAccessControlEnabled(false);
//directoryService.setExitVmOnShutdown(false);
directoryService.setShutdownHookEnabled( false );
directoryService.getChangeLog().setEnabled(false);

File workdir = new File(System.getProperty("java.io.tmpdir"), "apache-ds");
workdir.delete();
workdir.mkdirs();
directoryService.setWorkingDirectory(workdir);

partition = addPartition("testPartition", "c=RU");
addIndex("objectClass", "ou", "uid");

SocketAcceptor socketAcceptor = new SocketAcceptor(null);

ldapService = new LdapService();
ldapService.setIpPort(port);
ldapService.setSocketAcceptor(socketAcceptor);
ldapService.setDirectoryService(directoryService);

directoryService.startup();
ldapService.start();
}


public void applyLdif(File ldifFile) throws Exception {
new LdifFileLoader(directoryService.getAdminSession(), ldifFile, null).execute();
}



public void stop() throws Exception {
ldapService.stop();
directoryService.shutdown();
}


/**
* Add a new partition to the server
*
* @param partitionId The partition Id
* @param partitionDn The partition DN
* @return The newly added partition
* @throws Exception If the partition can't be added
*/
private Partition addPartition( String partitionId, String partitionDn ) throws Exception
{
Partition partition = new JdbmPartition();
partition.setId( partitionId );
partition.setSuffix( partitionDn );
directoryService.addPartition( partition );

return partition;
}


/**
* Add a new set of index on the given attributes
*
* @param partition The partition on which we want to add index
* @param attrs The list of attributes to index
*/
public void addIndex(String... attrs )
{
HashSet<Index<?, ServerEntry>> indexedAttributes = new HashSet<Index<?, ServerEntry>>();

for ( String attribute:attrs )
{
indexedAttributes.add( new JdbmIndex<String,ServerEntry>( attribute ) );
}

((JdbmPartition)partition).setIndexedAttributes( indexedAttributes );
}

public int getPort() {
return port;
}

}



Now we can use it in integration unit tests:


@BeforeClass
public static void oneTimeSetUp() throws Exception {

ApacheLDAPServer.getInstance().start();
ApacheLDAPServer.getInstance().applyLdif(
new File("target/test-classes/ldap/ldap-init.ldif"));
ApacheLDAPServer.getInstance().applyLdif(
new File("target/test-classes/ldap/ldap-fill-local.ldif"));
}

@AfterClass
public static void oneTimeTearDown() throws Exception {

ApacheLDAPServer.getInstance().stop();
}



Here is sample LDIF file that is needed for initialization:


dn: m-oid=1.2.3.4.5.6.1, ou=attributeTypes, cn=core, ou=schema
objectClass: metaAttributeType
objectClass: metaTop
objectClass: top
m-description: Sample attribute
m-equality: caseIgnoreMatch
m-name: bwIPAddress
m-oid: 1.2.3.4.5.6.1
m-ordering: caseIgnoreOrderingMatch
m-substr: caseIgnoreSubstringsMatch
m-syntax: 1.3.6.1.4.1.1466.115.121.1.44

dn: m-oid=1.2.3.4.5.6.2, ou=attributeTypes, cn=core, ou=schema
objectClass: metaAttributeType
objectClass: metaTop
objectClass: top
m-description: Sample attribute
m-equality: caseIgnoreMatch
m-name: bwNAI
m-oid: 1.2.3.4.5.6.2
m-ordering: caseIgnoreOrderingMatch
m-substr: caseIgnoreSubstringsMatch
m-syntax: 1.3.6.1.4.1.1466.115.121.1.44

dn: m-oid=1.2.3.4.5.6.3, ou=attributeTypes, cn=core, ou=schema
objectClass: metaAttributeType
objectClass: metaTop
objectClass: top
m-description: Sample attribute
m-equality: caseIgnoreMatch
m-name: bwMIN
m-oid: 1.2.3.4.5.6.3
m-ordering: caseIgnoreOrderingMatch
m-substr: caseIgnoreSubstringsMatch
m-syntax: 1.3.6.1.4.1.1466.115.121.1.44

dn: m-oid=1.2.3.4.5.6, ou=objectClasses, cn=core, ou=schema
objectClass: metaObjectClass
objectClass: metaTop
objectClass: top
m-description: Template scartel entry
m-must: bwIPAddress
m-must: bwMIN
m-must: bwNAI
m-name: bwMobileNodeSession
m-oid: 1.2.3.4.5.6
m-supobjectclass: top

dn: c=RU
objectClass: country
objectClass: top
c: RU

dn: bwIpAddress=0.0.0.150 , c=RU
objectClass: bwMobileNodeSession
objectClass: top
bwipaddress: 0.0.0.150
bwmin: 00-02-9A-00-00-10
bwnai: 00-02-9A-00-00-10


I use Maven for project management so it's pretty easy to add all needed libraries. However, blogs above maven configs are suitable only for Apache DS 1.5.5 which is not yet released (on this moment). I made my own dependency list for 1.5.4 and here it is:


<!-- Apache DS dependencies -->
<dependency>
<groupId>org.apache.directory.server</groupId>
<artifactId>apacheds-all</artifactId>
<version>1.5.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.directory.mina</groupId>
<artifactId>mina-core</artifactId>
<version>0.9.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.directory.mina</groupId>
<artifactId>mina-filter-ssl</artifactId>
<version>0.9.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.directory.server</groupId>
<artifactId>apacheds-core</artifactId>
<version>1.5.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.5.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.5.2</version>
<scope>test</scope>
</dependency>


So, this is a simpliest configuration for embedded java ldap server. You can add additional dependencies to support Kerberos authentication, other network protocols and so on. In 1.5.5 you only need to add apacheds-all module and maven will download all other stuff through transitive dependencies.

Ярлыки:


 

Let's start!

My new blog concerns programming and especially Java language.

I'm going to publish here some advanced programming knowledges that I'll gain during my job and education. The purpose of this diary is to not forget some techniques, patterns, etc. and share my knowledges with others.

So, let's start!

This page is powered by Blogger. Isn't yours?

Подпишитесь на каналы Сообщения [Atom]