Streaming movies from my Linux laptop to XBox

Hi

I have an XBox machine at home, and it’s great. I have a Linux based laptop – and it’s also great. However, during my Windows days I was able to use Windows Media Center to stream movies to my XBox – and I wanted to do that on my Linux box too.

Not too difficult.
Just read this article. Easy. However, it uses ethernet cable to connect XBox and Linux. Well, that’s no longer needed. Just replace, in the ushare.conf file the USHARE_IFACE=etho line with USHARE_IFACE=wlan0. That was enough.

Enjoy.

Connecting iReport to Vertica

I’m continuing my journey of connecting JasperReports and Vertica, and it’s not an easy task.
The Vertical team did some damage – they changed their JDBC driver class name (it used to be com.vertica.Driver and now it com.vertica.jdbc.Driver), so the iReport application doesn’t let you connect to the Vertica database, since you constantly get a ClassNotFoundException.
Have no fear – it’s easy to fix.

  1. Add the Vertica JDBC driver JAR to the iReport ClassPath. It can be done under Tools|Options–>ClassPath. Just click the “Add JAR” button and map it to the location of your JAR file
  2. Create a new XML file, with the following data (update to your environment):
    <?xml version="1.0"?>
    <iReportConnectionSet>
    	<iReportConnection name="Vertica" connectionClass="com.jaspersoft.ireport.samples.db.SampleDatabaseConnection">
    		<connectionParameter name="ServerAddress"><![CDATA[IP_ADDR]]></connectionParameter>
    		<connectionParameter name="SavePassword"><![CDATA[true]]></connectionParameter>
    		<connectionParameter name="Url"><![CDATA[jdbc:vertica://IP_ADDR:5433/DB_NAME]]></connectionParameter>
    		<connectionParameter name="JDBCDriver"><![CDATA[com.vertica.jdbc.Driver]]></connectionParameter>
    		<connectionParameter name="Database"><![CDATA[DB_NAME]]></connectionParameter>
    		<connectionParameter name="Password"><![CDATA[PASSWORD]]></connectionParameter>
    		<connectionParameter name="Username"><![CDATA[dbadmin]]></connectionParameter>
    	</iReportConnection>
    </iReportConnectionSet>
    
  3. Create a new Data Source. Click the Report Datasources icon, and instead of new, click import and choose the XML file you created.

Your report should now work with Vertica.

Connecting JasperReports to Vertica

I have a customer that asked me to build a Vertica environment and connect it to JasperReports. Fun!
So, it took a while (mostly due to technical difficulties on my end), but it works. And I thought I’d document how.

  1. Install Vertica. That’s an easy task, lots of documentation on the Vertica site. Frankly – I haven’t read any of it. Just clickty-click and you’re done.
  2. Create the Vertica database. Use /opt/vertica/bin/adminTools for that. Make sure you run it under the dbadmin user (use su - dbadmin if you have problems to login directly).
  3. Install Tomcat. I used Tomcat 6, but 7 is supported too.
  4. Install JasperReports Server (can be downloaded here). I used the WAR file version (had problems with the X Windows support over SSH) – see installation documentation here. This was not the easiest thing to do.
  5. Copy the Vertica JDBC driver to Tomcat (from /opt/vertica/java/lib/vertica_5.1.1_jdk_5.jar to TOMCAT_HOME/lib)
  6. Start Tomcat (using TOMCAT_HOME/bin/startup.sh)
  7. Log in to the Jasper Reports application at http://your_host:8080/jasperreports. Default username is jasperreports and the password is jasperreports too.
  8. Create a new DataSource in Jasper. For driver class enter com.vertica.jdbc.Driver. For URL enter jdbc:vertica://vertica_host:5433/db_name. User is dbadmin and password is the database password you entered when you created the database
  9. update

    Turns out I was overly optimistic. Although Jasper UI shows the connection works, reports can’t run with this connection. You need to use a JNDI Data Source connection. Easy to do:

    1. Open the context.xml file in the TOMCAT_HOME/webapps/jasperreports/META-INF
    2. Add the following lines:
      <Resource name="jdbc/vertica" auth="Container" type="javax.sql.DataSource"
      maxActive="100" maxIdle="30" maxWait="10000"
      username="dbadmin" password="test"
      driverClassName="com.vertica.jdbc.Driver"
      url="jdbc:vertica://localhost:5433/test" />
    3. Now create a JNDI based data source in Jasper (see here for more details)
    4. I have also saw that the TOMCAT_HOME/conf/Catalina/default/jasperreports.xml file needs to be updated, and contain the same code snippet from above. I have no clue why Tomcat doesn’t update this file automatically.
    5. Restart the Tomcat server

That’s it. Hope it helped 😉

Billing software evaluation

I’m doing a new project for a customer, who wants me to write the licensing/billing module in his PHP app. So, the first thing is to decide on the billing software to use. I came up with this table (kind of a braindump thing), trying to evaluate the different solutions I found.

Updated

# Item PayPal Chargify Zuora Plimus
1. API
2. Charge via API V V V V
3. Subscription registration via API V V V V
4. Allow changes in subscription plan/price via API ? V V V
5. Get billing information (invoices) via API V V V V
6. Notifications V (API) V- (not API, but can be automatic) V (API) ?
7. Send invoices to customers V V V V
8. Billing management
9. Discounts V V V
10. Chargeback V V V V
11. Custom workflows for issue management X X V ?
12. Prepay discounts V- Manual
13. Accept credit cards V V V V
14. Environment
15. Free test account V V V V
16. Site stores customer payment information V V V V
17. Integration with SF X X V X
18. Pricing 2.9% + 0.30c per transaction 99$/month (depend on number of customers), additions for gateways Not published 8% per transaction
19. Customer self service portal V V V V

What do you think? Any major player I’ve left out? Anything I should add to my criteria?

Update

I’ve started with PayPal – they have terrible documentation and API. Took me a day to actually do something – but it worked. Only then I discovered that subscriptions require a PayPal account. So I’m now evaluating Zuora. I’ll post my experience with them in future posts.

Improving authorization performance in Liferay

I have recently run a benchmark on a Liferay 6.1 portal. Most of the bottlenecks were the result of the portlets themselves, but a major point was the authorization mechanism of Liferay.
The way Liferay authorization works is that for every component on the screen an authorization check is made. Now, this makes sense. But the problem is that the default implementation is a bit naive – it goes to the database to check if the user has the correct authorization. And since rights can be inherited – each check goes multiple times to the database.
So, I set out to solve this irritating issue by using a cache. Now – this cache is naive too – if a user was granted a new role – a server restart is needed. But this implementation is easy to extend.

  1. Create a new class, that extends com.liferay.portal.security.permission.AdvancedPermissionChecker
  2. Open the portal-ext.properties file.
  3. Add the property permissions.checker={your class name} to it
  4. The class code should look like this:
    package com.tona.liferay.permission;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class TonaPermissionChecker extends
    		com.liferay.portal.security.permission.AdvancedPermissionChecker {
    
    	private static Map<PermissionKey, Boolean> permissionCache = new HashMap<PermissionKey, Boolean>();
    
    	public boolean hasPermission(long groupId, String name, String primKey,
    			String actionId) {
    
    		PermissionKey key = new PermissionKey(groupId, name, primKey, actionId);
    		if (permissionCache.containsKey(key)) {
    			return permissionCache.get(key);
    		}
    
    		boolean result = super.hasPermission(groupId, name, primKey, actionId);
    		permissionCache.put(key, result);
    
    		return result;
    
    	}
    
    	private class PermissionKey {
    		private long groupId;
    		private String name;
    		private String primKey;
    		private String actionId;
    
    		public PermissionKey(long groupId, String name, String primKey,
    				String actionId) {
    			super();
    			this.groupId = groupId;
    			this.name = name;
    			this.primKey = primKey;
    			this.actionId = actionId;
    		}
    
    		public long getGroupId() {
    			return groupId;
    		}
    
    		public void setGroupId(long groupId) {
    			this.groupId = groupId;
    		}
    
    		public String getName() {
    			return name;
    		}
    
    		public void setName(String name) {
    			this.name = name;
    		}
    
    		public String getPrimKey() {
    			return primKey;
    		}
    
    		public void setPrimKey(String primKey) {
    			this.primKey = primKey;
    		}
    
    		public String getActionId() {
    			return actionId;
    		}
    
    		public void setActionId(String actionId) {
    			this.actionId = actionId;
    		}
    
    		@Override
    		public int hashCode() {
    			final int prime = 31;
    			int result = 1;
    			result = prime * result
    					+ ((actionId == null) ? 0 : actionId.hashCode());
    			result = prime * result + (int) (groupId ^ (groupId >>> 32));
    			result = prime * result + ((name == null) ? 0 : name.hashCode());
    			result = prime * result
    					+ ((primKey == null) ? 0 : primKey.hashCode());
    			return result;
    		}
    
    		@Override
    		public boolean equals(Object obj) {
    			if (this == obj)
    				return true;
    			if (obj == null)
    				return false;
    			if (getClass() != obj.getClass())
    				return false;
    			PermissionKey other = (PermissionKey) obj;
    			if (actionId == null) {
    				if (other.actionId != null)
    					return false;
    			} else if (!actionId.equals(other.actionId))
    				return false;
    			if (groupId != other.groupId)
    				return false;
    			if (name == null) {
    				if (other.name != null)
    					return false;
    			} else if (!name.equals(other.name))
    				return false;
    			if (primKey == null) {
    				if (other.primKey != null)
    					return false;
    			} else if (!primKey.equals(other.primKey))
    				return false;
    			return true;
    		}
    	}
    }
    
  5. Package the class in a JAR file, and put in TOMCAT_HOME/webapps/ROOT/WEB-INF/lib

Call to undefined function mysql_pconnect()

Wow. This took ages.
A customer of mine has developed a PHP application on his windows machine (yeah yeah I know). I tried installing it on my Linux laptop – and all I got was a white page.
Well, loving the challenge, I started putting in debu prints in all the PHP files. Turns out the customer uses CodeIgniter, so I started with core/CodeIgniter.php, moved to core/Loader.php, core/db/DB.php and ended up with the mysql_driver.php.
Turns out I was crashing on this line:

return @mysql_pconnect($this->hostname, $this->username, $this->password);

The error message (after removing the @ of course) was
Call to undefined function mysql_pconnect()
So lame. I forgot to run sudo apt-get install php5-mysql. 2 hours of my life wasted 🙁

The dangers of high availability

About 15 years ago I heard someone giving a lecture on a system he managed. He claimed they need to provide 5 9’s of availability, as it’s an extremely critical system. Needless to say, he didn’t deliver 5 9’s. Not even one. The system worked perhaps 79.999% of the time. Not very surprising. But the real surprise here is that this level of availability was good enough.

People tend to think their applications require extreme high availability for a wide variety of reasons. However – most don’t need high availability.

Now, since high availability is so costly to implement (hardware costs, architectural and development costs, etc), I think you really need to ask yourself – does my application really need high availability – or am I taking all this effort just to soothe my ego?

There are levels of high availability, and think well before you answer. Do all of the users need access to the application 24*7? What are their working hours? Can some users experience failure while most users still work? Can users experience partial data loss (restart a wizard, or re-filling a form)?

I, for one, think that giving a good enough availability, and have a very good monitoring solution with someone to solve crashes on a 30 minute notice is probably good enough – and is much more cost effective.

Tunneling with JProfiler

I had some issues running JProfiler from a remote machine. I had a JBoss running on a remote Linux server, and for some reason, XWindows just didn’t work. Turns out I had to tunnel all my JProfiler connection, and luckily – that’s easy to do.
I typed a command on my own laptop (running Linux Mint)

ssh -f root@XXX.XXX.XXX.XXX -L 2000:localhost:8849 -N

And now, all I have to do is open a connection from JProfiler. I use attach to remote process, select localhost, port 2000, and that’s it – I can now profile the remote server.

FileDescriptor.sync()

First and foremost – a week ago, I never even knew this method existed in Java. Basically – it let you force the file writing to the disk. Turns out Arjuna (JBoss transactions) is using it in its ShadowStore class, to ensure transaction data is stored to disk. It makes sense – as they want to recover transactions in case of a server crash.
Now, if you read my last post, on the inflation of EJBs, you know that 200 EJBs working together is a mess. And I’ve reached a point where 15% of CPU time of a single transaction is spent on this FileDescriptor.sync() method. Since I couldn’t refactor the whole code – I had to think of another solution. Here goes.

I’ve written a new class, that extends ShadowStore.

public class TonaStore extends ShadowingStore {
    public TonaStore(ObjectStoreEnvironmentBean objectStoreEnvironmentBean) throws ObjectStoreException
    {
        super(objectStoreEnvironmentBean);
    	syncWrites = false;
    }
}

I deployed it to a JAR file, and placed it in the server/all/lib directory.

Now, I opened the /server/all/deploy/transactions-jboss-beans.xml file, and changed ActionStore section to the following:

    <bean name="ActionStoreObjectStoreEnvironmentBean" class="com.arjuna.ats.arjuna.common.ObjectStoreEnvironmentBean">

        <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="jboss.jta:name=ActionStoreObjectStoreEnvironmentBean", exposedInterface=com.arjuna.ats.arjuna.common.ObjectStoreEnvironmentBeanMBean.class, registerDirectly=true)</annotation>
        
        <constructor factoryClass="com.arjuna.common.internal.util.propertyservice.BeanPopulator" factoryMethod="getNamedInstance">
            <parameter>com.arjuna.ats.arjuna.common.ObjectStoreEnvironmentBean</parameter>
            <parameter>default</parameter>
        </constructor>
        <property name="objectStoreDir">${jboss.server.data.dir}/tx-object-store</property>
	<property name="objectStoreType">com.tona.ts.common.TonaStore</property>
    </bean>

I got almost a 100% increase in hits/second. Sweet.