Posts filed under ‘Recipies’

Multiple ActiveRecord connections without Rails

Here is a little trick that allows having connections to multiple databases with pure ActiveRecord.

First, a little recap. Here is the code for making a single connection:

require 'active_record'

ActiveRecord::Base.establish_connection(
  :adapter  => 'mysql',
  :database => $env[:db_name],
  :username => $env[:db_user],
  :password => $env[:db_pass],
  :host     => $env[:db_host])

class MyTable < ActiveRecord::Base
end

The nice thing with this approach is that any additional class will automatically reuse the defined connection.

However, if we need to have multiple connections the approach is a little different:

require 'active_record'

ActiveRecord::Base.configurations["db1"] = {
  :adapter  => 'mysql',
  :database => $env[:db1_name],
  :username => $env[:db1_user],
  :password => $env[:db1_pass],
  :host     => $env[:db1_host]
}


ActiveRecord::Base.configurations["db2"] = {
  :adapter  => 'mysql',
  :database => $env[:db2_name],
  :username => $env[:db2_user],
  :password => $env[:db2_pass],
  :host     => $env[:db2_host]
}

class Table1 < ActiveRecord::Base
  establish_connection "db1"
end

class Table2 < ActiveRecord::Base
  establish_connection "db2"
end

This approach allows defining any number of database connections and any number of tables on those connection. It also allows adding connections and classes dynamically based on some runtime information. The only drawback is that in each class you are required to define which connection needs to be used.

September 26, 2010 at 2:37 pm Leave a comment

HOWTO: Suppress EJBTHREE-1337 warning

If you are running JBoss 5.X with JBossWS there is an annoying warning that is printed each time a web service is called that looks like this:
EJBTHREE-1337: do not get WebServiceContext property from stateless bean context, it should already have been injected

First of all, don’t get alarmed – there is no actual problem. The warning is targeted at the framework developers and not at the end users – all it means is that JBossWS is using a recently deprecated API which still works. There is nothing end user can do to fix this and it doesn’t matter anyway since everything just works.

The problem however is that the warning clutters the log file and makes debugging harder than needed. It is easy to suppress it though and I will show you how.

First, locate jboss-log4j.xml file which should be found under ${JBOSS_HOME}/server/default/conf. If you are using a runtime configuration other than default, locate the file under configuration that you actually use. This file is used to configure logging output of the JBoss.

Inside the file search for “Limit categories” – you should find a list of <category> definitions. Edit it to look something like this:

   <!-- ================ -->
   <!-- Limit categories -->
   <!-- ================ -->

   <!-- Suppress EJBTHREE-1337 warning -->
   <category name="org.jboss.ejb3.stateless.StatelessBeanContext">
     <priority value="ERROR"/>
   </category>

You are basically telling JBoss to suppress any WARN or lower messages from the class that generates those warnings. Now just restart JBoss and the warning should disappear.

September 14, 2009 at 10:58 am 1 comment

HOWTO: Simple profiling with Spring AOP

As part of its AOP package, Spring has a very nice little utility class called CustomizableTraceInterceptor which can be used to easily profile and debug your application using automatic logging of method invocations, including name of the method, parameters (using toString()), return values and invocation times. It doesn’t replace proper debugger and/or profiler but it can provide you a lot of interesting data with minimal cost. It can be even used in production as it can be turned on/off easily.

So how does it work? It uses Spring AOP capabilities to wrap around beans you choose to add a little code that will output invocation data before the method is called, and will output return values and execution time after it finishes. The best practise it to apply the interceptor on client facing beans – in other words entry points of your server so you can easily monitor what is called, when it’s called and how long did it take.

So how to add it? First thing you need to define a subclass of CustomizableTraceInterceptor like this:


public class MyTraceInterceptor extends CustomizableTraceInterceptor {

  protected void writeToLog(Log logger, String message, Throwable ex) {
    if (ex != null) {
     logger.info(message, ex);
    } else {
     logger.info(message);
    }
 }

 protected boolean isInterceptorEnabled(MethodInvocation invocation, Log logger) {
   return true;
 }
}

By overriding writeToLog() method you control output severity and destination. Overriding isInterceptorEnabled() allows you to finely control when tracing should happen – you could for example decide not to trace methods that start with “foo*”. Simply returning true means trace always.

Now that you have your interceptor defined it’s time to apply it to your beans. Add this to your spring.xml

    <bean name="traceInterceptor" class="MyTraceInterceptor" dependency-check="none">
        <property name="enterMessage" value="ENTER: $&#91;targetClassShortName&#93;.$&#91;methodName&#93;($&#91;arguments&#93;)"/>
        <property name="exitMessage"
                  value="EXIT: $&#91;targetClassShortName&#93;.$&#91;methodName&#93;() : $&#91;invocationTime&#93;ms : $&#91;returnValue&#93;"/>
    </bean>

    <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator" dependency-check="none">
        <property name="beanNames" value="*RequestListener,*Notifier"/>
        <property name="proxyTargetClass" value="true"/>
        <property name="interceptorNames">
            <list>
                <value>traceInterceptor</value>
            </list>
        </property>

        <property name="order" value="2"/>
    </bean>

First definition instantiates the interceptor and defines format of the trace messages.

Second bean applies the interceptor to your beans using “beanNames” to select the beans with the wild card. If you use “*” it will mean it will wrap all your beans, so you probably want to input something meaningful here.

And that’s it. Rerun your app, call some methods and open up log files. You will see the traces there.

September 2, 2009 at 8:48 am Leave a comment

HOWTO: Run tests with Embedded JBoss

I’ve needed to create an environment for running unit tests on EJB3 JBoss application this week. There were few GOTCHAs so for the benefit of future generations here is a simple recipe for running your unit tests on Embedded JBoss.

First a link to Embedded JBoss wiki page. You can find some information there. Also download the latest version (I used beta3.SP9) from there. We are going to use Maven to get the jars but you still need the configuration files from the download.

Ok, lets setup our maven dependencies.

First define repository if you don’t have it yet:


<repository>
   <id>jboss</id>
   <name>Jboss Repo</name>
   <layout>default</layout>
   <url>http://repository.jboss.com/maven2</url>
  <snapshots>
     <enabled>false</enabled>
   </snapshots>
   <releases> 
     <enabled>true</enabled>
   </releases>
 </repository>

Now add actual dependencies for embedded jboss:


<dependency>
  <groupId>org.jboss.embedded</groupId>
  <artifactId>jboss-embedded-all</artifactId>
  <version>beta3.SP9</version>
  <scope>test</scope>
 </dependency>

<dependency>
   <groupId>org.jboss.embedded</groupId>
   <artifactId>jboss-embedded</artifactId>
   <version>beta3.SP9</version>
   <scope>test</scope>
 </dependency>

<dependency>
   <groupId>org.jboss.embedded</groupId>
   <artifactId>hibernate-all</artifactId>
   <version>beta3.SP9</version>
   <scope>test</scope>
 </dependency>

<dependency>
   <groupId>org.jboss.embedded</groupId> 
  <artifactId>thirdparty-all</artifactId>
  <version>beta3.SP9</version>
   <scope>test</scope>
 </dependency>

Now lets create a test class. It will look just like your normal test class but you need to add the following method to start and deploy JBoss


@BeforeClass
 public static void startJboss() throws Exception {
   Bootstrap bootstrap = Bootstrap.getInstance();
   bootstrap.bootstrap();

   bootstrap.deployResourceBase(MyBeanOne.class);
   bootstrap.deployResourceBase(MyBeanTwo.class);
 }

Two things happen here. First, bootstrap() method launches Embedded JBoss with basic configuration. With standard JBoss it would be enough since it would automatically deploy all ears. In this case though, we need to explicitly tell it what to deploy – that’s what deployResourceBase() command does.
Now that you have Embedded JBoss starting and deploying before your tests, you can write any code that tests those beans. For example:


@Test
 public void testMe() throws NamingException {
   InitialContext context = new InitialContext(); 
   MyBeanLocal bean = (MyBeanLocal)context.lookup("MyBean/local");
   bean.doSomething();
 }

And now the GOTCHAs.

First for JBoss to run it needs some configuration. Remember that zip you downloaded? Open it up, find bootstrap folder inside and then copy entire contents of that folder into test/resources folder of your maven module. That’s the basic configuration. If you want something additional, like your own datasource, you can add it into the test/resources/deploy folder as you would normally add it to deploy folder of standard JBoss.

We are not done yet. If you are running on Java 6 and the chances are that you are, it will still not work. You must add the following JVM property to your unit test configuration to force JVM to run in Java 5 compatible mode: -Dsun.lang.ClassLoader.allowArraySyntax=true

And the last thing –  if you are running from IDE you are probably deploying from exploded classes folder and not from packager jar/ear. If so, there is a good chance that Embedded JBoss will fail because it won’t have enough file handles to properly deploy your classes. To fix it on Linux use ‘ulimit -n <some large number>’ to increase the number of file handles. On windows look up your own solution.

And that’s it. You now have working Embedded JBoss test environment. Congratulations 🙂

@Test
public void testMe() throws NamingException {
InitialContext context = new InitialContext();
MyBeanLocal bean = (MyBeanLocal)context.lookup(“MyBean/local”);
bean.doSomething();
}

August 20, 2009 at 9:03 am 6 comments

How to: implement singleton EJB in JBoss

As promised in the rant post – here is the simple and elegant way of creating a singleton bean in JBoss.

@Service
@Local(MySingletonLocal.class)
public class MySingletonBean implements MySingletonLocal {
  private Object sharedData = new Object();  

  public void workOnSharedData() {
    // TODO do your things here
  }

}

As you can see, it’s really simple and it looks exactly the same as the @Stateless bean definition except that you replace it with @Service annotation. In order for this to compile you must link with jboss-ejb3-ext-api.jar (found at JBOSS_HOME/common/lib/ directory) during compilation because that annotation is proprietary for JBoss.

Ok, we have the bean – but how we can use it? Well, that’s even easier – just use @EJB annotation the same way you would use it for any regular stateless bean.


@Stateless
public class SingletonUserBean implements SingletonUser {

    @PersistenceContext private EntityManager em;
    @EJB private MySingletonLocal mySingleton;

     // ..... the rest of it

}

And that’s it – everything will be properly injected for you by the container.

I’ve tested this solution in the JBoss 5.0.1GA – it is supposed to work with older versions as well, but you should try it yourself.

One last note – starting from EJB3.1 spec they are adding @Singleton annotation which is going to be the standard solution for these types of problems. One of the nicer things about it is that they are also adding synchronization support with annotations so we wouldn’t have to deal with it manually (the hard part of singleton beans like that is handling the concurrency issues since it’s shared for all application). And even though it is not part of the spec it is assumed that the new @Singleton beans will be shared in the cluster – so if you have few application servers for high availability or load balancing, you will be able to use this technology to share state between them (for example counting requests for the cluster and not just sinlge server). See more details here.

April 7, 2009 at 7:59 am 1 comment


Calendar

April 2024
S M T W T F S
 123456
78910111213
14151617181920
21222324252627
282930  

Posts by Month

Posts by Category