Labels

April 17, 2013

Java Memory in open VZ machines

Hi,

I ran into troubles while trying to run a play application. The server is hosted in an openVZ container, which lead to problems during jvm memory initialization when I entered à play start command :

Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.

After googling a while, this SO thread gave me the answer which I'll summarize here.

If you're in a hurry, here is the answer : edit the [JRE location]/lib/[Archi (ex : i386)]/jvm.cfg file and alter the first uncommented line.

Move from


-client IF_SERVER_CLASS -server
-server KNOWN
-hotspot ALIASED_TO -client
-classic WARN
-native ERROR
-green ERROR

to:
#-client IF_SERVER_CLASS -server
-client KNOWN
-server KNOWN
-hotspot ALIASED_TO -client
-classic WARN
-native ERROR
-green ERROR

From what I understand, with the initial configuration, when trying to launch a java process if the machine has 2G+ memory installed  it fires up the JVM in server mode.
Server mode means the JVM will ask for all the memory requested in contiguous memory blocks, and openVZ is not able to do that.

The -client KNOWN option will ask for memory on the fly, thus removing the problem meentionned above.

Hope this help.


April 09, 2013

Yeoman : TypeError('Arguments to path.join must be strings');

Hi all,

Today I was playing with this great Yeoman tool. Basically it's a scaffolding tool (yo) combined with a building (grunt) and dependency manager tool (bower) for building front end apps.



That tool (or that tooling set) is really, really great and you should check it out.

Set up is really easy, everything is packaged as Node.js modules. Only thing I didn't see first when installing the stack : Node.js is fully supported until version 0.8.x for now. Running a higher version (0.10 in my case) will lead to problems like this

path.js:360
        throw new TypeError('Arguments to path.join must be strings');
              ^
TypeError: Arguments to path.join must be strings
    at path.js:360:15
    at Array.filter (native)
    at Object.exports.join (path.js:358:36)
    at Object. (/opt/nodejs/node-v0.10.0-linux-x64/lib/node_modules/yo/node_modules/yeoman-generator/node_modules/bower/lib/core/config.js:41:22)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)


This error doesn't come right away, I had it when trying to use the angular generator (angular:route) to be precise.

Hope this help.

March 08, 2013

Linux : look for a string pattern in files in a particular directory and sub directories

Say you want to search for a string pattern in all files included in a directory, and even in its subdirectories. Well, here is the magic command :

find /directory/where/to/look/for -exec grep -nH "my string to look for" {} \;


The command is pretty self explanatory :

/directory/where/to/look/for
The ditectory where you will lokk for files, including all of its sub-directories

-nH
the 'n' option will print line numbers, and 'H' file paths.

Add a number in those options, and bash will print out 'x' the x lines before and after the line matching the pattern (i.e. -nH5 will print out five lines after and before matching line)


"my string to look for"

The pattern to look for. Quotes are only mandatory if your search pattern includes spaces.

You can of course use other find and grep options, i.e. find -name *.xml to filter only xml files.

Example :

 find . -exec grep -H 10108 {} \;

./blabla.text:7:ds10108
Binary file ./jre1.6.0_21/win/bin/fontmanager.dll matches
Binary file ./jre1.6.0_21/win/lib/rt.jar matches


January 17, 2013

JAX-RS / Jersey CORS Filter and JAXB List


I had to implement CORS functionnalities for cross domain javascript in my REST app.
I stumbled upon the excellent solution posted by Usul.

Basically, you have to implement a ContainerResponseFilter that will check request headers and set response headers :
 public ContainerResponse filter(ContainerRequest req, ContainerResponse contResp) {
 
        ResponseBuilder resp = Response.fromResponse(contResp.getResponse());
        resp.header("Access-Control-Allow-Origin", "*")
                .header("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
 
        String reqHead = req.getHeaderValue("Access-Control-Request-Headers");
 
        if(null != reqHead && !reqHead.equals(null)){
            resp.header("Access-Control-Allow-Headers", reqHead);
        }
 
        contResp.setResponse(resp.build());
            return contResp;
    }

This solution worked great until I had to return a List of objects. In this particular case, the Response.fromResponse method returned a ResponseBuilder object in which I had lost my collection type, resulting in a nice exception saying that no MessageBodyWriter was found.

A message body writer for Java class java.util.ArrayList, and Java type class java.util.ArrayList, and MIME media type application/json was not found

To bypass it, instead of using the nice Response.fromResponse method, I had to set the headers "manually" in the ContainerResponse object by accessing the header map :

public ContainerResponse filter(ContainerRequest req, ContainerResponse contResp) {
  contResp.getHttpHeaders().add("Access-Control-Allow-Origin", "*");
  contResp.getHttpHeaders().add("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
  
  String reqHead = req.getHeaderValue("Access-Control-Request-Headers");

  if (null != reqHead && !reqHead.equals(null)) {
   contResp.getHttpHeaders().add("Access-Control-Allow-Headers", reqHead);
  }
  return contResp;
 }

Doing it this way, response object isn't modified and type information isn't lost. JAXB is now able to marshall json or xml either in single object or collection case of return.

January 15, 2013

Fix Subclipse setup in RAD 7.0

My RAD subclipse setup was broken. I had to work on that computer, wokrpsace was already set up when I started to use it and that was fine for me. But now, time to commit... and I get a nice error popup saying that "This client is too old to work with working copy" (error message is pretty clear).

So what to do ? well,  for sure not what I did : install the latest subclipse version (1.8.x) without checking first the SVN server version. In fact, i should have install the 1.6.x subclipse plugin.

I then tried to install the 1.6.x version via the update site, but I guess that after that my RAD setup didn't like to have both subclipse version installed...

RAD 7.0.x doesn't make it easy to uninstall plugins, so here's what I did to fix it and have 1.6 subclipse plugin working :
  • Shut down RAD
  • Move all thee org.tigris.something jars and folders out of the plugins eclipse directory. That made both 1.6.x and 1.8.x versions not to work.
  • Restart RAD
  • Use the following item menu to check what's really missing : Help / Software updates / Manage configuration



  • From there I was able to 
    • Disable 1.8.x version (still don't know how to remove it entirely though)
    • Diagnose what jars were missing to make the 1.6.x work fine : before I put the right jars back to the plugin directory, the corresponding items were flagged with a red cross in the above snapshot (just like a java compilation problem). Using the Display properties link helped me to retrieve the "good" jars and make the red cross disappear.
What made this a bit painful was that I had to restart RAD workspace after each item fix : fix JNA library by replacing the jar > restart RAD > check that red cross disappeared > see cwhat's nex jar missing > fix xxx library ... > ...
Without restarting in between each fix, my workspace would crash. 


January 07, 2013

RAD 7 & WAS 6.1 : server1 open for e-business .... but stucked with "starting" status

I've probably been a bit too rude with my WAS 6.1 instance.
With no reason (or so it seems to me...), the server instance was starting (I had the "server open for e-business" sentence, and was able to access my app), but RAD wouldn't detect it (stucked in the "starting..." state, so not able to do anything inside RAD).

Switching the communication type in the server view from RMI to SOAP, restart the server, and then back to RMI solved my problem.

HTH.

January 03, 2013

Jersey : inject Form params into java custom object with @Inject

Working with Jersey, I had to handle search form parameters in a POST method.
Well, with the number of form parameters growing, adding @FormParam in the method signature isn't really a sustainable solution.

Starting to think about how to code this, and looking at how was jersey injecting stuff like Context objects, I was really happy to find out that this feature exists, but isn't really documented.

Yoryos Valotasios found this some times ago, saving me headaches, and published his home made solution that made him realize the feature already exist : http://blog.valotas.com/2011/01/resteasy-form-annotation-for-jersey.html

Thanks to him for saving me time !

Note, this is a Jersey feature, not a JSR 311 one.

So, to the point :

//Resource class
@Path("/customers")
public class CustomerResource { 

  @Post
  public Response addCustomer(@Inject CustomerFormParam customerForm) {
     // your code
  }
}

// The handler object
public class CustomerFormParam {

  @FormParam("firstName")
  private String firstName;
 
  @FormParam("lastName")
  private String lastName;
  ...
}

Well... that's it !

Neat isn't it ?