miércoles, 12 de agosto de 2015

Maven Plugin ClassLoader conflicts

Why Maven oh why????
We love you, we really do.  But some times you just manage to piss off your fans.

Let me tell you guys a story...

Imagine you have a pom.xml file that contains the following dependency:


  com.my.artifact.group
  my-artifact
  1.0.0

Now for the sake of the story let's say you have your custom plugin, or any for that matter:

  com.my.plugin.group
  my-plugin
  1.0.0

Now the hero in this story is happy with his new pom file and ready to make it build so he goes ahead an do:

mvn clean package


BUT WAIT, the build failed!!!!
The exception is not really importan but, again, for the sake of the story let's say it's a NoSuchMethodException.

Afterwards our hero starts tracking the cause of the error, and it so happens that the class with a missing method is part of
my-artifact
But how comes?
When he goes and looks for that class code the method is there.
Weird eh?

He keep on and decides checking different versions of the same artifact and he finally finds out that version 2.0.0 of the artifact does not have such method.

- But wait, I'm not using that artifact am I? - he thinks for himself

He does:
mvn dependency:tree

And also
mvn dependency:resolve

And as he thought the version is the correct one.
After a few hours of useless tests he decides to check the plugin, as it's the only thing left to check.

When he runs:
mvn dependency:tree

He sees something odd:
com.my.artifact.group:my-artifact:2.0.0

- OMFG 2.0.0, WTF!!!!! -  He thinks


And here the story ends!




Now for the more realistic part of this blog, the problem here is Maven uses the same classloader to load both the plugin's dependencies as well as the ones of the project you are trying to build.

So far so good, the problem comes when, like in the story two different versions of the same jar are not compatible. In our story they remove a whole method.

It get's worst there is no easy way track this issue as the logs will only who show that there is an issue but they will also show that the jar being loaded is the one declared in the pom's project giving you now clue on where the problem is coming from.


Solutions:


Well not much to do here. If you control the plugin you could just go ahead and check that pom and exclude the dependency (if possible).

If you don't control it, you can try excluding the dependency or the transitive dependency. Although after a quick search doesn't seems to be that easy.

Any way, the conclusion here is:
* Next time you face a similar problem check the plugin
* To Maven team, guys please find a way to separate the plugin classloader from the one of the application being build.


P.S.: didn't have time to create nice code snippets sorry!




miércoles, 13 de mayo de 2015

Dependency Hell

So it seems I'm on a roll... No long ago I stumble upon the jar hell issue, several times in a short time span and thus I write a small post about it. Now I stumble upon the Dependency Hell issue. So what is that all about??? Have you ever come across a maven error like:
failed: An API incompatibility was encountered while executing
Well if you had, the you're fu%#&. Well not that much but it's an interesting problem to have. Now I have found this article quite useful http://discursive.com/2014/03/17/maven-3-2-1-provides-a-new-cure-for-dependency-hell/, but in short:

When you have a dependency hell problem, is because maven is loading the same jar but different versions of it and they happen to be incompatible

Not really helpful right?
What it means is either, a dependency of your project of a transitive dependency is in conflict. Now when I say transitive, I mean transitive something in the third or forth degree may cause a problem. That's a dependency of a dependency of a dependency of a dependency. Not only that, plugin dependencies come into the game too.

Now all this this is lovely, how do I solve this mess???

There is no straight forward way, I'm sorry to say, at least none that I know of.
Usually  the firsts lines of the error will point you to the class and the method that is causing the problem.
From there, you first need to find which maven artifact contains that class.
One you have located that artifact, look for it in the stack trace chances are that you'll find it more than one time.
Now here is when it get's funny, you need to pick one of the versions of this artifact and take it out.
The problem is that the stacktrace is not arrange in a hierarchical way so when you see the module you want to take out it may be because it's in your pom, or it's a transitive dependency of the artifact just above (in the stack trace I mean). But it could also mean that the one above is a transitive dependency of the one just above or to levels up.

So here you will have to start using mvn dependency:tree, and play Find my artifac. Now this command will not output all the transitive dependencies but just a few levels of the whole tree (may be 2 or 3). The other problem is it will only show the version of the artifact that's being loaded during the build (not that the other are not loaded but you get my point).

Any ways, removing unnecessary dependencies ore telling a dependency to exclude a particular jar will probably solve the problem, the fun of this game it to spot the correct one.


I know this post is not perfect guide on how to solve this problem but I hope it'll give you a better idea of what you're dealing whit and an idea on how to start solving it.



viernes, 17 de abril de 2015

XPath and Name Spaces, don't you hate them too??

How about running a XPath expression from Java?
Pretty straight forward right, oh wait NAMESPACE!!!!

Here's a example on how to create your xpaht parser and the more complex Name Space Context.
Let's start with the NameSpaceContextImpl

Now the actual Xpath parser imple: Hope it helps guy!!!

The famous Jar Hell issue

So I reckon I'm not the first one to have this problem. I'm certainly not the one who will tell you how to solve it BUT!!!!

Here is a really small example about using the JHades tool 

Why am I posting this?
Because the example in the home page is a little bit outdated and if you search JHades for the maven dependency the first 4 links you hit get it wrong.


Maven Dependency


Java Code

You should place this in some place that you are sure it'll get run during building.
If you have issues during tests. Just create a test where the test method has this code.

Hope this helps!

viernes, 5 de diciembre de 2014

Change Maven Default JDK in MAC

Long time no see!!!!!

So I thought of type this one down before I forgot about it.

Now that Oracle start releasing at an increased rate I reckon it may be useful.

Soooo how to change the jdk maven uses to build you app:

1. Locate/create the file .mavenrc in your home
2. add the following line to it:
export JAVA_HOME=/Library/Java/JavaVirtualMachines/${actual_jdk_version}/Contents/Home

At the time of me writing this that placeholder value was: jdk1.7.0_51.jdk


Hope it helps you!

jueves, 2 de enero de 2014

The Freaking Command key

Hi all, long time no see HAPPY 2014.

So as this new year is starting I'm already having problems, I'm a mac user basically cause I don't have to pay for the Mac hehe.

Any way every once in a while the Command key in my keyboard stops working which makes me crazy!!!!!

So here I found a really nice fix:

If you type "killall Dock" into the command line in Terminal, it restarts the Dock.

This is, the Dock was causing the command key not to work.
As usual it wasn't me how find this out here is the link to the forum where I found the solution. 

I hope it helps someone else.

martes, 17 de septiembre de 2013

Analyzing Threads

Hi there,

So I could take the time to write something about how to analyze threads right?

Thing is there is are tons of data around this out there, so instead of that I'll only share this post from dZone I've find:

http://architects.dzone.com/articles/how-analyze-java-thread-dumps

It is actually brilliant not only gives you context but it shows you how to read the dumps and gives you a hint on some patters.

The other thing I've got to share is a profiling tool I've been checking out (didn't know it existed) and it quite nice:

http://www.yourkit.com/

The tool allows you to hock to a VM and check what's going on in regards to CPU usage, thread count, memory (and it generations) etc.
It's really quite descriptive but it comes with a catch, you have to pay for it. Then again it has a trial period.

Well that's all folks!!!

martes, 16 de julio de 2013

GIT rever to a particular commit


That stupid little silly  thing we always forget how to do, right?

So how, HOW many times did you find your self having to do such thing due to, lets say, a less than brilliant coworker eh?

In my case, usually the less than brilliant coworker is me!!! 
And I always forget how to do this, so this is how


 git reset --hard d7517455bb118142bf12d08628a780d5372da045


It doesn't get easier than this.

In a near future (that is when I have time) I plan to post a summary of all this GIT stuff.

Hope it helps guys and girls....
Who am I laying to we know no girls read this :P

martes, 21 de mayo de 2013

The Secret language of WSDL - The entry point

Hi there, if you like me has to deal with a lot of service definition you'll be wise if you read how that WSDL actually works.

If you, like me, are to lazy to actually learn all that you may want to read this post.

So  this post series (at least I hope to create a series out of this) will try to sum up the main thing one should know about how to read from a WSDL.

We will start by the main thing, at least for me, the ENTRY POINT.

So what to I mean by Entry Point.
For me it's just the Java class that will actually allow you to access all the operations defined in the service definition.

Where is this defined in a WSDL, easy just look for this tag:

<wsdl:service name="UserServiceImplService">
    <wsdl:port binding="tns:UserServiceImplServiceSoapBinding" name="UserServiceImplPort">
        <soap:address location="https://fake.service.provider.com/Some-path-dev/services/admin/UserService"/>
    </wsdl:port>
</wsdl:service>
 


Now this portion of the WSDL will basically describe the entry point of some service.

Once you run your wsdl2java tool to generate the Java code,  what class should I look for?

Well for starters I'll go with: UserServiceImplService
Which is the value of the name parameter in the wsdl:node service.

This class will allow you to access the proxy class (which is no other than the port), this proxy class will expose all the operations that are defined to be accessible for this service.

How do I find this port/proxy class?
Well..... try looking for: UserServiceImplPort
Which is no other than the value of the name parameter in the node: wsdl:port


This has worked out for me in the past I hope it helps you!

BTW do thank my good friend the Master of CXF Gustavo

Cheers

martes, 14 de mayo de 2013

Multipart message with jersey

Hi there, so I'm really happy to see that there is people at least accessing this blog.
Honestly I was intented only for me but if it helps others BRILLIANT, one thing though: DO COMMENT.

Most useful data is usually find in the comments.

Now to today's topic: multi part messages.
In short multipart is a message that could be compose by more than one content type.
All this is part of the HTTP specification and in different RFC of it the guys creating the specification had defined different multiparts.

Today I'll show you how to handle two of them, which are more or less the same, with Jersey Client.



MULTIPART-MIXED
In this example I'll be sending a form with part of the message as XML and the other is the content of a file encoded in BASE64.

            // Asume that this method will just return you a builder 
        WebResource.Builder builder = getBuilder(user, password, url, null);

        // Add headers
        builder = builder.type(MultiPartMediaTypes.MULTIPART_MIXED);

        MultiPart multiPart = new MultiPart();

        // XML Document

         String xmlContent = getXMLContent();
         multiPart = multiPart.bodyPart(new BodyPart(xmlContent, MediaType.APPLICATION_XML_TYPE));

        // File content
        BodyPart bodyPart = new BodyPart();
        multiPart = multiPart.bodyPart(bodyPart);


        InputStream fileInputStream = getFileInputStream();
        bodyPart.setEntity(getFileContentInBase64(fileInputStream));

        ClientResponse clientResponse = builder.post(ClientResponse.class, multiPart);




MULTIPART-FORMDATA
For this example I'll be just sending some plaint text fields in the form and then the content of a file.

            // Asume that this method will just return you a builder 
        WebResource.Builder builder = getBuilder(user, password, url, null);

        // Add headers
        builder = builder.type(MediaType.MULTIPART_FORM_DATA);

        FormDataMultiPart form = new FormDataMultiPart();
        form.field("document[file_name]", fileName);
        form.field("document[description]", fileDescription);
        form.bodyPart(new StreamDataBodyPart("document[attached_file]", fileInputStream));

        ClientResponse clientResponse = builder.post(ClientResponse.class, form);




As you can see there is not much difference but the content-type header.
The other big difference is that the multipart-formdata does has the shape of a form.
This is you set a name of a property in the form and it's value.

But in multipart-mixed you just add body parts that can be what ever you want.
Of corse under the hod the serialized message looks quite different. In the mixed message you'll see some separators and the fact that the file is encoded, this is plain text but encoded.

Any ways this may save you some time.

Hope you like it.      

martes, 16 de abril de 2013

Gson and how nice it is

Tired of Jackson are you?
Do you want to serialize a POJO and not have to add all those annotations?
Just want to try a different way to deal with Json?

The I have an answer for you: Google Gson.

Gson is the Google library to deal with JSON and serialization, but in a easier way.
For starters you don't need to use annotations for the properties or the methods, it uses (out of the box) the POJO convention and introspection to serialize the class.

So for example if you just want to serialize some Java class you have you'll have to do the following:
Gson gson = new GsonBuilder().create();
gson.toJson(anObject);

And to de-serialize it you'll do:
Gson gson = new GsonBuilder().create();
gson.fromJson(aJsonString, anObject.getClass());


Now one thing I just keep forgetting how to do (hence the name of the blog) is how to deserialize a plain old collections let say a List of Strings, and here is how:
 
import java.lang.reflect.Type;
Type type = new TypeToken<List<String>>() { }.getType();
List<String> aList =  new Gson().fromJson(jsonData, type);

As you can see it is quite simple to use, and of course this is just a really really really small port of what you can do with it, but it was a nice excuse for me to post how to deserialize a collection :P.  

For more information just check the Gson site here :

https://sites.google.com/site/gson/gson-user-guide

Any way I hope you can use it.
 

Dealing with GZIP Content

So .... Long time no see eh?
Oh well there are many reasons for that but truth is "you don't care about that".
Let's jump then into this post topic, which is ZIPED content.

As you may or may not know web servers can send you the content you are requesting in a compress way. Main reason for this is, of course, cause you save bandwidth.
Problem being, you have to deal with that content.
As it turns out you usually come across this when you are creating some sort of HTTP client to consume something and when you try to print the data you can no read it (this is what happened to me).

Easiest way to know for sure that the server is doing this is, checking the following HTTP header:

Content-Encoding: gzip 

This tells you that the "content" has been "gziped", quite obvious rigtht?

Now lets talk about code, how do I deal with this.
Well if you are a smart chap and you are using Jersey Client, this is how:


import com.sun.jersey.api.client.filter.GZIPContentEncodingFilter;

List<ClientFilter> clientFilters = new ArrayList<ClientFilter>();
clientFilters.add(new GZIPContentEncodingFilter(false));


if (clientFilters != null) {
  for (ClientFilter clientFilter : clientFilters) {
      client.addFilter(clientFilter);
  }
}


As you can imagine the client is the Jersey Client, and basically what this code does is to add a filter.
For Jersey filters are plugin of code that in the end knows how to do certain stuff with the payload you send.
In this case this filter "GZIPContentEncodingFilter" knows how to add the HTTP header I showed you before BUT ALSO, it knows how to zip the payload you're seeing.

Now that I've showed you how to handle this with Jersey I've also thought it'll be a good idea to show you just how to decode and encode any content in the same way, and this is how:

Decode: 
InputStream io = (InputStream) someInputStreamYouHad;
String payload = new String(IOUtils.toByteArray(new GZIPInputStream(io)));


Encode:

OutputStream os = new ByteArrayOutputStream();
OutputStream realOs = new GZIPOutputStream(os);
      
realOs.write(payload.getBytes());

realOs.close();
payload = os.toString();


And that's it, hope it helps you/me.

viernes, 11 de enero de 2013

Maven Archetype from Existing Project

Hi there,

So this weeks I've been having to mess around with Maven, in particular with archetypes.
Being new at this particular aspect of the Maven world I started where almost anyone will the Maven documentation page.

Any way.......

Thing is, this helped me a lot to understand the structure of a Maven archetype project but it didn't get me to create an archetype in an easy way.
In the end I found this blog.

As it turns out, the easiest way to create a Maven archetype is using an existing maven project.
Which makes senses.
As with anything in life if you like to create a template for something it's easier to create that something an then extract the template.

So this is the case, and the way to achieve this is:

mvn archetype:create-from-project

This will create a maven archetype from a project and will leave this new archetype project in:

target/generated-sources/archetype/

Now that you have you're base archetype you can start to tune it, and when you're ready to go just do:

mvn install

This will install the archetype in your local m2 repo.

Finally for those of you who don't know how to use this archetype one it's in place, this is the way:

mvn archetype:generate -DarchetypeGroupId={group.id.defined.in.the.archetype} -DarchetypeArtifactId={artifact-id-defined-in-the-archetype}



And that's it, have fun


martes, 8 de enero de 2013

Out of Memory with Maven & MAVEN_OPTS

Have you ever got an error like this:


java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:2786)
at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:94)
at java.util.jar.JarVerifier.update(JarVerifier.java:194)
at java.util.jar.JarFile.initializeVerifier(JarFile.java:322)
at java.util.jar.JarFile.getInputStream(JarFile.java:388)
at sun.misc.URLClassPath$JarLoader$2.getInputStream(URLClassPath.java:69


Well this is the easy solution, increase the memory of the JVM.

BUT HOW IF I'M BUILDING WITH MAVEN???

God question, and the answer is:

export MAVEN_OPTS=-Xmx512m


Of course this will follow the same rules as for the vm arguments for the JVM, so please modify your memory limit accordingly.

Also this export command, for you Mac users, will only set the env var for the current terminal not for all the future ones.

Hope you find this useful I know I'll keep coming back to this post just to remember this.


viernes, 14 de septiembre de 2012

Once upon a time CURL

Have you had the chance to work with REST???

Something that I've come to learn working with REST is that people working with it are fond of the CURL command line.

Wikipedia defines CURL as:

"is a computer software project providing a library and command-line tool for transferring data using various protocols."

Thing is, I really don't like it. Not because it's a bad tool but because I just don't want to learn yet another command line, let's face it I'm lazy. Any way this people I was talking about have so much faith in CURL that may come to demand you to post the output of a CURL execution to validate what ever you're saying about a REST call.

Providing all this I thought it may be worth to write a small post about the really basic things that you can do with CRUL.

Now the prototype of the command it's quite simple:


curl [options] [URL...]


The options portion is the one that really matters.
Here is a list that I found useful, but keep an eye on the post for I may keep updating it:

 -H  this is for header. Any valid HTTP may be used here.

It's useful  for things like Authorization.

-X this can be used for for HTTP verbs

Like so -X DELETE, -X POST


So this would be how a valid call looks like:

curl  -H "Authorization: Basic sdaqwrdsfdsfafdszadsafdsafdsfad3" -X DELETE http://somehost.com/something?queryparam=somethingelese

Any way, for now this suits me but would you need more data please refer to:


Of course over there you'll find all there is to find about CURL, but I just like to post here things that I tend to forget.

Enjoy





viernes, 7 de septiembre de 2012

Retry Strategy Implementation

Hi, this small portion of code is to be used when ever you need to perform a task that may fail and in which event you should retry a predefined amount of times.

I won't be explaining the code in detail but if you have questions please to comment :D.

RetriableTask Class:


public class RetriableTask<V> implements Callable<V> {

    private static final int DEFAULT_RETRY_ATTEMPTS = 3;
    private static final int DEFAULT_TIME_BETWEEN_RETRIES = 1000;

    private Callable<V> task;
    private int retryAttempts;
    private int timeBetweenRetries;

    private int retryCount;

    public RetriableTask(Callable<V> task) {
        this(task, DEFAULT_RETRY_ATTEMPTS, DEFAULT_TIME_BETWEEN_RETRIES);
    }

    public RetriableTask(Callable<V> task, int retryAttempts, int timeBetweenRetries) {
        this.task = task;
        this.retryAttempts = retryAttempts;
        this.timeBetweenRetries = timeBetweenRetries;
        this.retryCount = retryAttempts;
    }

    @Override
    public V call() throws Exception {

        while (true) {
            try {
                return task.call();
            } catch (InterruptedException e) {
                throw e;
            } catch (CancellationException e) {
                throw e;
            } catch (Exception e) {
                retryCount--;
                if (retryCount == 0) {
                    throw new RetryException(retryAttempts + " attempts to retry failed at " + timeBetweenRetries
                            + "ms interval", e);
                }
                Thread.sleep(timeBetweenRetries);
            }
        }
    }

}


How to use the class above:

Put this code in a method of your choosing. Of course this can be perfected and used in such way as to change what ever task you want to perform in runtime.

Callable<T> task = new Callable<T>() {
@Override
public T call() throws Exception {
    return // WHAT EVER YOU NEED TO ACTUALLY DO;
        }
};
       
       
String response = "";
try {
    response = new RetriableTask<String>(task).call();
} catch (RetryException e) {
    // THIS WILL BE CATCH WHEN:
    // The call to the task fails and all the retries were exausted

    // So do what ever you need to do when your operation fails:
    // HERE
} catch (Exception e) {
    // If you reach this point something else
    // besides the actuall retry failed
    throw new RuntimeException(e);
}

Attach existing directory to a new GIT Hub Repo

So........

This one may sound familiar to you right?

You started working on something and at some point some one tells you: "oh!!!! brilliant upload it Git Hub so I can take a look at it"

And ad that point is when the problem starts.

So how do you update code you are working on (this is an existing project) to a repo you are about to create.

Well this is basically solved in StackOverflow BUT allow me to replicate it here ok?



1. Create the remote repository, and get the URL such asgit://github.com/youruser/somename.git

If your local GIT repo is already set up, skips steps 2 and 3

2. Locally, at the root directory of your source, git init

3. Locally, add and commit what you want in your initial repo (for everything, git add . git commit -m 'initial commit comment')to attach your remote repo with the name 'origin' (like cloning would do)

4. to attach your remote repo with the name 'origin' (like cloning would do) git remote add origin [URL From Step 1]

5. git pull origin master

6. to push up your master branch (change master to something else for a different branch): git push origin master

So this worked pretty well for me to have a look at it.

I case you wander this is the StackOverflow link

martes, 14 de agosto de 2012

Complex types & Cloud connectors with Mule ESB

Hi there, have you ever worked with Mule ESB?

Quite nice, free and open source ESB that you should really check!

Now they have this concept of CloudConnector, which is basically an easy plug and play way to make you ESB talk to other service's API. Here is a list of all of them as of today.

Now this post is not about how to use nor create a  CloudConnector. This is just a short post about how to deal with a  CloudConnector when its methods returns Complex Types.

A Complex Type it's nothing else than a POJO, BUT the fact that it's a POJO make it some how a little more complex to use it the first time.

Why????

Well because the output of any call to a  CloudConnector it's something that you can not use out of the box just because you don't know what does it expose, I mean the getters of the object.
And the problem here is that when you are modifying a Mule configuration file (which is the way to program Mule ESB) there is no autocomplete like in Eclipse to help you.


So, now that I've stablished the problem I shall offer you the solution.
Mule ESB has native support for Groovy scripts, which allows you to access any object.

So let's take for instance a call to the LinkedIn Cloud Connector they offer:


<linkedin:get-profile-for-current-user config-ref="LinkedinConf"/>

When set up properly this should return you data from the profile of the currenent user. And it does but it does so by returning a POJO.
So if you want any useful information from it you should access its getter methods. BUT WAIT I DON'T KNOW THE CODE OF IT, even more important I don't have it.

And that's where Groovy comes in handy, for this will tell you what you can ask for this POJO returned:

<linkedin:get-profile-for-current-user config-ref="LinkedinConf"/>
<logger message="#[groovy:payload.getClass().getDeclaredMethods().toString()]" level="INFO" doc:name="Logger"/>


When put together this to tags in you Mule config file you'll be able to check all the methods exposed by this POJO and hopefully find something you can use.

Of course this is nothing more than the use of java reflection but for a newbie in both Java and Mule ESB this post my help you.


So that's it, have fun.

martes, 7 de agosto de 2012

Working with ZIP files in memory

Long time no see right?

Today's topic is ZIP files. I'm going to tell you how to work with ZIP files in memory.

The use case comes handy when your code has no access to the actual file persisted in the file system. The most common scenario, I think, it's when a file it's being uploaded or transferred  through any end point.

As it turns out Java has quite a lot of library build in in its java.util.zip packages to make this magic happens (kind of logical it's in the zip package eh? I just DIDN'T see it before :P ).

These are the main classes we are going to be using:

  • java.util.zip.ZipEntry
  • java.util.zip.ZipInputStream
  • java.util.zip.ZipOutputStream
As you may already notice, if we can access the actual file we should have access to something right?
Well that something it's an InputStream, not any input stream of course but a ZipInputStream, so lets see how to create one out of any common InputStream:

InputStream zipFileInputStream;
ZipInputStream inputZipFile = new ZipInputStream(zipFileInputStream);

Pretty easy, right? 
Of course, bear in mind that the use case here assumes that you have access to an input stream, could be the actual file, an http etc. The point is that ones you have the input stream you won't have to use anything else to mange the ZIP file.

Now we are going to see two use cases that may come handy, first to read a particular file/s inside a ZIP file and second how to add content to the ZIP file.

Let us begin with the first use case how to get a particular file from inside the ZIP file:

ZipEntry entryFile;
try {
  entryFile = inputZipFile.getNextEntry();
  while (entryFile != null) {
    String[] nameAndExtention = StringUtils.split(entryFile.getName(), ".");
    if (nameAndExtention.length >= 2) {
      String extension = nameAndExtention[nameAndExtention.length - 1].toLowerCase(); 
      if (extension.equals(FILE_EXTENTION)) {        

        int n;
byte[] buf = new byte[1024];         

        ByteArrayOutputStream tmpOutStream = new ByteArrayOutputStream(1024);

while ((n = inputZipFile.read(buf, 0, 1024)) > -1) {
          tmpOutStream.write(buf, 0, n);
}

fileList.add(new String(tmpOutStream.toString()));
    }
  }
  entryFile = inputZipFile.getNextEntry();
 }
} catch (IOException e) {
  e.printStackTrace();
}

So as you can see the first thing we use here is the ZipEntry class. This is what the ZipFileInputStream returns when we iterate through it. It represents a file inside the the ZIP file and its related metadata.
So from this point onwards it's quite simple you'll j just need to play with the ZipEntry API to get what you need.
In my case I was looking for files with a certain extension(word of advise though the getName method returns the canonical name of the file).

So once you selected the files you needed you may want to read them right?
As you may have guessed by now this is achieved by this code:
        int n;
byte[] buf = new byte[1024];         

        ByteArrayOutputStream tmpOutStream = new ByteArrayOutputStream(1024);

while ((n = inputZipFile.read(buf, 0, 1024)) > -1) {
          tmpOutStream.write(buf, 0, n);
}

fileList.add(new String(tmpOutStream.toString()));

And the first question should be but how does the ZipFileInpuStream which file to read and the answer it's easy. 
When you do:

inputZipFile
.getNextEntry()

This works as a pointer for the ZipFileInpuStream, and internally position the pointer to the beginning of the entry it just returned to you. So when you do getNextEntry the pointer moves forward to the next entry. 
Thus when you do:
inputZipFile.read

You are going to be reading until the end of the entry you are on, this is the end of the file you selected.
Finally I just do a tmpOutStream.toString() but because the files I work with are text based files.

In this way you can read the content of any file inside a ZIP file.

Now for the second use case,  add content to the ZIP file.
The idea it's pretty much the same BUT you'll have to do something like this:

ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

ZipOutputStream zipOutputFile = new ZipOutputStream(outputStream);


ZipEntry newZipentry = new ZipEntry("some_name");
zipOutputFile.putNextEntry(newZipentry);
zipOutputFile.write(newFileContent.getBytes());


As you can see you first need to create an output file first.
So you'll say "BUT YOU SAY ADD CONTENT TO A ZIP FILE" well we ARE doing that it's just a matter of creating your zipOutpuFile from an original content.


Any way I hope you've enjoy it.
Also take a look at the following web sites I used to code this:







miércoles, 18 de julio de 2012

Run Single Test in Maven

If you guys read the reason I started this blog, you'll recall  that it was just to summarize stupid stuff one always forget when coding.
And so here is one of them, how to run just a single test from the command line with maven.
Well let me just C&P the data from the Apache Maven site


To run this through Maven, set the test property to a specific test case.
mvn -Dtest=TestCircle test
The value for the test parameter is the name of the test class (without the extension; we'll strip off the extension if you accidentally provide one).
You may also use patterns to run a number of tests:
mvn -Dtest=TestCi*le test
And you may use multiple names/patterns, separated by commas:
mvn -Dtest=TestSquare,TestCi*le test
I know I know this has not actual merit but hey think of this blog as place were you can find this kind of things because, except from one or two original things this is what you'll find.