Defining system variables in Mac OS X

Submitted by Jochus on Tue, 23/10/2012 - 17:07 | Posted in: Mac
Posted in


If you want to define a system variable in Mac OS X, and you want all of your applications (commandline, GUI, ...) to be able to pick them up - then you need to follow the steps:

  • Open a terminal
  • Execute the command:
    $ sudo nano /etc/launchd.conf
    Remark: In my case, the file didn't exist, so don't worry if you need to create it
  • Insert the following text (I added 2 examples: JAVA_HOME and JREBEL_HOME)
    # Set environment variables here so they are available globally to all apps
    # (and Terminal)
    #
    # After editing this file run the following command from the terminal to update 
    # environment variables globally without needing to reboot.
    # NOTE: You will still need to restart the relevant application (including 
    # Terminal) to pick up the changes!
    # grep -E "^setenv" /etc/launchd.conf | xargs -t -L 1 launchctl
     
    setenv JAVA_HOME /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
    setenv JREBEL_HOME /Applications/eclipse/plugins/org.zeroturnaround.eclipse.embedder_5.0.1.RELEASE-201207191833/jrebel

JSF Facelets ui:repeat tag breaks redisplaying of values in a form when validation failed

Submitted by Jochus on Thu, 20/09/2012 - 20:52 | Posted in: Java
Posted in


I'm currently working on a project which uses the Mojarra 2.0.3 JSF reference implementation. I encounterd a really strange bug today ...
Imagine you have the following form (code entered in pseudocode, just to make it compact and clear):

<h:form>
    <div>
        <h:inputText id="field1" value="#{Bean.singleField.value}" required="true"/>
    </div>
    <div>
         <ui:repeat value="#{Bean.listOfFields}" var="field">
             <h:inputText value="#{field.value}"/>
         </ui:repeat>   
    </div>
    <h:commandButton value="Submit" type="submit" action="#{Bean.doAction} />
</h:form>

Scenario:
Now, when you don't provide a value in field1 (you do provide values in the other fields) and you submit the form, validation will fail (because of the required attribute).

The problem:
When the form rerenders, all values in the input fields inside the ui:repeat tag are gone.

The solution
After some research, we found out we stumbled into the following bug: http://java.net/jira/browse/JAVASERVERFACES-1807. So we should upgrade our JSF implementation (which isn't an option for the moment). Luckily, we are using Richfaces in our project so we could replace the ui:repeat tag by the A4J equivalent: aj4:repeat.

Removing "[HornetQServerImpl] Security risk! It has been detected that the cluster admin user and password have..." message

Submitted by Jochus on Mon, 10/09/2012 - 16:38 | Posted in:

If you want to get rid of this warning during the JBoss 6.X startup:

WARNING [HornetQServerImpl] Security risk! It has been detected that the cluster admin user and password have not been changed from the installation default. Please see the HornetQ user guide, cluster chapter, for instructions on how to do this.

... you can change the hornetq-configuration.xml configuration. Add the following lines in the configuration tag element:

<cluster-user>guest</cluster-user>
<cluster-password>guest</cluster-password>

Debugging passivation errors in JBoss AS

Submitted by Jochus on Mon, 06/08/2012 - 21:58 | Posted in: Java
Posted in

The problem

Did you ever have issues passivating/serializing beans? Was the error/stacktrace very unclear? Do you want to know what exactly goes wrong in the passivation process? Passivation errors can be a real pain in the ass, ... but they can also be simply clarified.

An example

We were constantly getting the following stacktrace when one of our stateful session beans was passivated. The session bean was passivated after idling the application for 5 minutes. So you login into the application, you setup and use the bean. And then, you leave the bean for more then 5 minutes idle.

Example stacktrace:


....
at org.jboss.serial.io.JBossObjectOutputStream.writeObjectOverride(JBossObjectOutputStream.java:181)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326)
at org.jboss.serial.io.MarshalledObject.(MarshalledObject.java:51)
at org.jboss.ejb3.stateful.StatefulBeanContext.writeExternal(StatefulBeanContext.java:1048)
at org.jboss.serial.persister.ExternalizePersister.writeData(ExternalizePersister.java:58)
at org.jboss.serial.objectmetamodel.ObjectDescriptorFactory.describeObject(ObjectDescriptorFactory.java:276)
at org.jboss.serial.objectmetamodel.DataContainer$DataContainerDirectOutput.writeObject(DataContainer.java:206)
at org.jboss.serial.io.JBossObjectOutputStream.writeObjectOverride(JBossObjectOutputStream.java:181)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326)
at org.jboss.ejb3.cache.simple.StatefulSessionFilePersistenceManager.passivateSession(StatefulSessionFilePersistenceManager.java:393)
at org.jboss.ejb3.cache.simple.SimpleStatefulCache.passivate(SimpleStatefulCache.java:397)
at org.jboss.ejb3.cache.simple.SimpleStatefulCache$SessionTimeoutTask.run(SimpleStatefulCache.java:301)
Caused by: java.lang.NoClassDefFoundError: org/jboss/wsf/spi/serviceref/ServiceRefMetaData
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2427)
at java.lang.Class.getDeclaredMethod(Class.java:1935)
at org.jboss.serial.classmetamodel.ClassMetaData.lookupMethodOnHierarchy(ClassMetaData.java:102)
at org.jboss.serial.classmetamodel.ClassMetaData.lookupInternalMethods(ClassMetaData.java:432)
at org.jboss.serial.classmetamodel.ClassMetaData.(ClassMetaData.java:122)
at org.jboss.serial.classmetamodel.ClassMetamodelFactory.getClassMetaData(ClassMetamodelFactory.java:350)
at org.jboss.serial.objectmetamodel.ObjectDescriptorFactory.describeObject(ObjectDescriptorFactory.java:168)
at org.jboss.serial.objectmetamodel.DataContainer$DataContainerDirectOutput.writeObject(DataContainer.java:206)
at org.jboss.serial.persister.ArrayPersister.saveObjectArray(ArrayPersister.java:110)
at org.jboss.serial.persister.ArrayPersister.writeData(ArrayPersister.java:101)
at org.jboss.serial.objectmetamodel.ObjectDescriptorFactory.describeObject(ObjectDescriptorFactory.java:276)
at org.jboss.serial.objectmetamodel.DataContainer$DataContainerDirectOutput.writeObject(DataContainer.java:206)
at org.jboss.serial.persister.RegularObjectPersister.writeSlotWithFields(RegularObjectPersister.java:182)
at org.jboss.serial.persister.ObjectOutputStreamProxy.writeFields(ObjectOutputStreamProxy.java:79)
at org.jboss.serial.persister.ObjectOutputStreamProxy.defaultWriteObject(ObjectOutputStreamProxy.java:68)
at java.util.Vector.writeObject(Vector.java:1012)
... 261 more
at java.util.Vector.writeObject(Vector.java:1012)
... 261 more
Caused by: java.lang.ClassNotFoundException: org.jboss.wsf.spi.serviceref.ServiceRefMetaData from BaseClassLoader@36eb1ba3{vfs:///Applications/jboss-6.1.0.Final/server/default/conf/jboss-service.xml}
at org.jboss.classloader.spi.base.BaseClassLoader.loadClass(BaseClassLoader.java:480)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
... 278 more

You could think you're missing a library. In this case, ServiceRefMetaData is part of the jbossws-spi.jar. I really spent a lot of time figuring out why this class is missing. But my conclusion is: JBoss is putting you into the wrong direction. You are spending time solving an exception, which is actually be thrown by a lot of other exceptions.

The solution

First of all, decrease the idleTimeoutSeconds of statefull session beans. This will speed up the passivation process, as also the generation of stacktraces:

  • go to $JBOSS_HOME/server/default/deploy/ejb3-interceptors-aop.xml
  • search for:
       <domain name="Stateful Bean" extends="Base Stateful Bean" inheritBindings="true">
          <!-- NON Clustered cache configuration -->
          <annotation expr="class(*) AND !class(@org.jboss.ejb3.annotation.Cache) AND !class(@org.jboss.ejb3.annotation.Clustered)">
             @org.jboss.ejb3.annotation.Cache ("SimpleStatefulCache")
          </annotation>
          <annotation expr="class(*) AND !class(@org.jboss.ejb3.annotation.PersistenceManager) AND !class(@org.jboss.ejb3.annotation.Clustered)">
             @org.jboss.ejb3.annotation.PersistenceManager ("StatefulSessionFilePersistenceManager")
          </annotation>
          <annotation expr="class(*) AND !class(@org.jboss.ejb3.annotation.CacheConfig) AND !class(@org.jboss.ejb3.annotation.Clustered)">
             @org.jboss.ejb3.annotation.CacheConfig (maxSize=100000, idleTimeoutSeconds=300, removalTimeoutSeconds=0)
          </annotation>
          ...
  • change idleTimeoutSeconds from 300 to 30

Next, you need the source code of the JBoss Serialization project. You can get all source code here: http://anonsvn.jboss.org/repos/jbossserialization/tags/. If you don't know the version of JBoss Serialization, look into the MANIFEST.MF file of jboss-serialization.jar. JBoss 6.1.0.Final is using JBSER_1_0_3_GA for example.
Once you checked out the source code, add the project to Eclipse (there's a .project file, so importing is easy). Put a breakpoint in the class: org.jboss.serial.persister.RegularObjectPersister on line 127.

Finally, attach your debugger to your JBoss installation. When the stacktrace is generated, the debugger of Eclipse will be activated. Attach the source code by choosing: workspace > jboss-serialization.

Now simply follow the stacktrace to figure out on which property passivation is failing:

CueGenerator 1.0.0

Submitted by Jochus on Sat, 14/07/2012 - 13:27 | Posted in: Java
Posted in

The problem

I have a mixed MP3 liveset of a DJ and I need to burn it on a CD. Yes, the question will pop up: "OMG! CD?! Do they still exist?". Sure, everybody is using iPod, MP3 player, etc, etc, ... now, but I really need to burn it to disc.

I have a tracklist which tells me how long the individual tracks last. So based on this information, I could build a CUE file. This CUE file can be delivered to "whatever" burning software. It will burn the MP3 file to disc, but it will make indexes when a new individual track starts. More information about CUE files: http://en.wikipedia.org/wiki/Cue_sheet_(computing)"

Seems great, and I'm lucky, because there are a lot of CUE generators on the web:

But, the problem with each of these generators, is the timing input. You have to manually add the time of track 1 on track 2, track 2 on track 3, etc, etc, ...

Example:
Track 01 takes 06:42
Track 02 takes 04:12

I just want to provide the above numbers into the generator, but according to the CUE definition, I have to input:


TRACK 01 AUDIO
TITLE "Reverence"
PERFORMER "Faithless"
INDEX 01 00:00:00
TRACK 02 AUDIO
TITLE "She's My Baby"
PERFORMER "Faithless"
INDEX 01 06:42:00
TRACK 03 AUDIO
TITLE "Take the Long Way Home"
PERFORMER "Faithless"
INDEX 01 10:54:00

Of course, you can do this quickly yourself or by Excel, but I'm a software engineer, so I developed my own application ;-)!

The solution

  • Create a CSV file, having the following format:

    ##GENRE##
    ##DATE##
    ##PERFORMER##
    ##TITLE##
    ##FILE##
    ##TRACK_01_ARTIST##;##TRACK01_TITLE##;##TRACK_01_MINUTES##;##TRACK_01_SECONDS##
    ##TRACK_02_ARTIST##;##TRACK02_TITLE##;##TRACK_02_MINUTES##;##TRACK_02_SECONDS##
    ...
  • Download the following pom.xml and source file src/main/java/be/jochusonline/cuegenerator:
    <project>
    	<modelVersion>4.0.0</modelVersion>
    	<groupId>be.jochusonline</groupId>
    	<artifactId>cuegenerator</artifactId>
    	<version>1.0.0</version>
     
    	<dependencies>
    		<dependency>
    			<groupId>net.sf.opencsv</groupId>
    			<artifactId>opencsv</artifactId>
    			<version>2.3</version>
    		</dependency>
    	</dependencies>
    </project>

    package be.jochusonline.cuegenerator;
     
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.IOException;
    import java.text.DecimalFormat;
     
    import au.com.bytecode.opencsv.CSVReader;
     
    public class CueGenerator {
     
    	private static final String FILE = "/Users/jochen/Documents/Tmp/armin01.csv";
     
    	public static void main(String[] args) {
    		File csvFile = new File(FILE);
    		CSVReader reader = null;
     
    		if (!csvFile.exists()) {
    			System.err.println("File '" + FILE + "' does not exist.");
    		} else {
    			try {
    				/** INIT **/
    				int i = 1;
    				int minutes = 0;
    				int seconds = 0;
    				DecimalFormat formatter = new DecimalFormat("00");
    				reader = new CSVReader(new FileReader(FILE), ';');
    				String[] nextLine;
     
    				/** START OUTPUT **/
    				// Genre
    				nextLine = reader.readNext();
    				System.out.println("REM GENRE \"" + nextLine[0] + "\"");
     
    				// Date
    				nextLine = reader.readNext();
    				System.out.println("REM DATE \"" + nextLine[0] + "\"");
     
    				// Performer
    				nextLine = reader.readNext();
    				System.out.println("PERFORMER \"" + nextLine[0] + "\"");
     
    				// Title
    				nextLine = reader.readNext();
    				System.out.println("TITLE \"" + nextLine[0] + "\"");
     
    				// File
    				nextLine = reader.readNext();
    				System.out.println("FILE \"" + nextLine[0] + "\" MP3");
     
    				// Tracks
    				while ((nextLine = reader.readNext()) != null) {
    					// Track
    					System.out.println("  TRACK " + formatter.format(i) + " AUDIO");
    					System.out.println("    TITLE " + "\"" + nextLine[1] + "\"");
    					System.out.println("    PERFORMER " + "\"" + nextLine[0] + "\"");
    					System.out.println("    INDEX 01 " + formatter.format(minutes) + ":" + formatter.format(seconds) + ":00");
     
    					// Calculate time
    					minutes += Integer.parseInt(nextLine[2]);
    					seconds += Integer.parseInt(nextLine[3]);
    					while (seconds >= 60) {
    						seconds -= 60;
    						minutes++;
    					}
     
    					// Next track
    					i++;
    				}
     
    				System.out.println("\nControl check: total time of MP3 should be: " + minutes + ":" + seconds);
    			} catch (FileNotFoundException fnfe) {
    				fnfe.printStackTrace();
    			} catch (IOException ioe) {
    				ioe.printStackTrace();
    			} finally {
    				if (reader != null) {
    					try {
    						reader.close();
    					} catch (IOException e) {
    						e.printStackTrace();
    					}
    				}
    			}
    		}
    	}
    }
  • Run mvn eclipse:eclipse on a command prompt. You need Maven to perform this operation. You can download it from: http://maven.apache.org/. This operation will generate a .project file. Import that project into Eclipse.
  • Once imported in Eclipse, use the built-in run dialog. Eclipse will output the file to the console
  • At the bottom of the file, there's an extra check to be sure you didn't provide any incorrect data

Running memtest from Ubuntu Live CD 10.10

Submitted by Jochus on Mon, 02/07/2012 - 23:15 | Posted in: Linux
Posted in


In previous versions of the Ubuntu Live CD, you were able to select the memtest application on the startup process of the Live CD.
After booting the Ubuntu 10.10 Live CD, I've noticed I was immediately forwarded to the installer :-/ ...

In order to startup memtest, press F1 on the first screen of the Ubuntu Live CD. The boot process will ask you your language. Afterwards, you can select Test my memory.

Simulating slow network performance on a Mac

Submitted by Jochus on Tue, 19/06/2012 - 21:07 | Posted in: Mac
Posted in


If you ever want to simulate a slow performance network, you can use the following script on a Mac:

#!/bin/sh
#
# Use ipfw to throttle bandwidth.
# usage:
# ./throttle.sh     # Throttle at default (60KB/s)
# ./throttle.sh 5   # Throttle at custom speed (5KB/s)
# ./throttle.sh off # Turn throttling off
 
# flush rules
ipfw del pipe 1
ipfw del pipe 2
ipfw -q -f flush
ipfw -q -f pipe flush
 
speed=60
[ ! -z $1 ] && speed=$1
 
if [ "$1" == "off" ]; then
    echo "disabling BW limit."
    exit
else
    # simulate slow connection <to specific hosts>
    echo "enabling bw limit at ${speed}KByte/s"
    ipfw add pipe 1 ip from any to any
    ipfw add pipe 2 ip from any to any
    ipfw pipe 1 config bw ${speed}KByte/s
    ipfw pipe 2 config bw ${speed}KByte/s
fi

(source)