Piotr Gabryanczyk’s Blog

Java, Refactoring, AOP, Spring, DDD, TDD, etc.

  • Blogroll

    • I have joined Anti-IF Campaign

Archive for March, 2007

Closures in Java – catching up with Smalltalk?

Posted by Piotr Gabryanczyk on March 31, 2007

I was recently very happy to discover that there is proposal for closures in java. I have been waiting for this to happen since I haven’t even started programming in java in 1998, when I learned Smalltalk and wrote quite a useful system within two weeks in it.

I like most of the ideas in the proposal – good job gentelman! (no ladies participated yet…)

One thing which I find annoying is the declaration of types for the parameters of the closure, i.e.

runWithinTransaction(){
Transaction txn, Session s =>
...
}

It seams to me that if runWithinTransaction() accepts {Transaction txn, Session s => boolean} closure type, it is kind of redundant to repeat the types of parameters in the closure itself. So I would appreciate a bit of syntactic sugar here (or actually lack of it) and do it as follows:

runWithinTransaction(){
txn, s =>
...
}

Or even like other languages (Smalltalk, Ruby):

runWithinTransaction(){ |txn, s| ... }

I know I might sound like an ignorant here. The compiler writers will have more difficult job with guessing types of the parameters.
Purists might also start crying about lack of explicity here, as you can’t see the parameters type at the first sight… Come on it is no worse than casts when using collections in java under 1.5.

I wish we will see closures in java soon!

Advertisements

Posted in java, jvm | Leave a Comment »

Web Services in Java 6 – Finally simple!

Posted by Piotr Gabryanczyk on March 30, 2007

Web services always have been pain in Java. Finally in 1.6 they work out of the box.
What a relief… Sun is changing his policy of creating complex APIs, so you can not use them until some vendor implements layer of code on top of it…

I wonder when they add first() and last() methods on the list interface…

Anyway, web services are now as simple as they should have been from the beginning. Good job Sun!

Check the link below forn simple hello world example:
http://weblogs.java.net/blog/vivekp/archive/2006/12/webservices_in.html

Posted in java | 1 Comment »

What makes a good Software Engineer?

Posted by Piotr Gabryanczyk on March 25, 2007

Algorithms

I recently came across Cedric Beust’s post about new book “Algorithms“, by Sanjoy Dasgupta, Christos Papadimitriou and Umesh Vazirani. It is a good book, but I wanted to write about something else.

Algorithmics vs Design skills

Cedric’s post started a discussion on what is more important, knowledge of algorithms or good software design. One of the comments by Chris Johnston says:
“…When I was taking my CompSci degree, the first thing the prof said to us in my first comp sci course was that we were not there to study programming; we where there to study algorithms…”

I have seen this approach at my uni as well. For some time I was even proud of it. This made me feel better then “the rest of the crowd” who learn VB and think they are qualified. Unfortunately it turned out in “real live” that my algorithmic knowledge hasn’t been used much. And thing I was lacking a lot was good design principles, which I was never taught at uni as my professors where so focused on making me a scientist rather then good software engineer. In the world of complex software systems it is often much more important to create APIs and programs which are simple to understand and modify or maintain.

Please do not think that I underestimate algorithmic skills. I believe it is essential that developers have strong algorithmic background, but you can never forget that it is not the only thing which makes a good developer.

What do YOU think makes a good developer?

Posted in algorithmics, programming | 1 Comment »

Preventing Spring Context to be loaded more than once.

Posted by Piotr Gabryanczyk on March 21, 2007

Problem:

I have nested import statements in spring context files:

a.xml

<beans>
<import resource="b.xml"/>
<import resource="c.xml"/>
...
</beans>

b.xml

<beans>
<import resource="d.xml"/>
<import resource="e.xml"/>
...
</beans>

c.xml

<beans>
<import resource="d.xml"/>
<import resource="g.xml"/>
...
</beans>

When we load a.xml, both b.xml and c.xml will try to load d.xml. Spring will detect it on the bean level and will override beans already loaded and print “Overiding bean definition for bean” message. But it also means instantiation of overriden bean and lot of expensive preprocessing. (more about the problem…) In some cases (JMX bean registration, etc.) it might even cause spring context loader to stop loading the beans and closing the application.

Solution:

We want to prevent Spring from loading files already loaded. The following class will do this for us:

 1 import java.io.IOException;

 2 import java.net.URL;

 3 import java.util.Set;

 4 import java.util.TreeSet;

 5

 6 import org.springframework.beans.factory.BeanDefinitionStoreException;

 7 import org.springframework.beans.factory.support.DefaultListableBeanFactory;

 8 import org.springframework.beans.factory.xml.ResourceEntityResolver;

 9 import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;

10 import org.springframework.context.support.ClassPathXmlApplicationContext;

11 import org.springframework.core.io.Resource;

12

13 public class IgnoringDuplicateBeansClassPathXmlApplicationContext extends ClassPathXmlApplicationContext {

14     private Set<String> loadedLocations;

15

16     // (PG) Lazy init is needed as the method is called from superclass constructor

17     // (PG) I dont like it!!!

18     public Set<String> getLoadedLocations() {

19         if (loadedLocations == null) loadedLocations = new TreeSet<String>();

20         return loadedLocations;

21     }

22

23

24     public IgnoringDuplicateBeansClassPathXmlApplicationContext(String configFile) throws org.springframework.beans.BeansException {

25         super(new String[]{configFile});

26     }

27

28     public IgnoringDuplicateBeansClassPathXmlApplicationContext(String[] configFiles) {

29         super(configFiles);

30     }

31

32     protected DefaultListableBeanFactory createBeanFactory() {

33         return new IgnoringDuplicateBeansBeanFactory(getInternalParentBeanFactory());

34     }

35

36

37     protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException {

38         // Create a new XmlBeanDefinitionReader for the given BeanFactory.

39         XmlBeanDefinitionReader beanDefinitionReader = new IgnoringDuplicateFilesBeanDefinitionReader(beanFactory);

40

41         // Configure the bean definition reader with this context's

42         // resource loading environment.

43         beanDefinitionReader.setResourceLoader(this);

44         beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

45

46         // Allow a subclass to provide custom initialization of the reader,

47         // then proceed with actually loading the bean definitions.

48         initBeanDefinitionReader(beanDefinitionReader);

49         loadBeanDefinitions(beanDefinitionReader);

50     }

51

52     public class IgnoringDuplicateFilesBeanDefinitionReader extends XmlBeanDefinitionReader {

53

54         public IgnoringDuplicateFilesBeanDefinitionReader(DefaultListableBeanFactory beanFactory) {

55             super(beanFactory);

56         }

57

58         public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {

59             String location = getURL(resource).toString();

60             if (getLoadedLocations().contains(location)) {

61                 logger.warn("Ignoring already loaded context [" + resource.getFilename() + "] - " + location);

62                 return 0;

63             } else {

64                 getLoadedLocations().add(location);

65                 return super.loadBeanDefinitions(resource);

66             }

67         }

68

69         private URL getURL(Resource resource) {

70             try {

71                 return resource.getURL();

72             } catch (IOException e) {

73                 throw new RuntimeException(e);

74             }

75         }

76     }

77 }

78 
 1 import org.springframework.beans.factory.BeanDefinitionStoreException;

 2 import org.springframework.beans.factory.BeanFactory;

 3 import org.springframework.beans.factory.config.BeanDefinition;

 4 import org.springframework.beans.factory.support.DefaultListableBeanFactory;

 5 import org.springframework.util.Assert;

 6

 7 public class IgnoringDuplicateBeansBeanFactory extends DefaultListableBeanFactory {

 8     public IgnoringDuplicateBeansBeanFactory(BeanFactory beanFactory) {

 9         super(beanFactory);

10     }

11

12     public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)

13             throws BeanDefinitionStoreException {

14

15         Assert.hasText(beanName, "'beanName' must not be empty");

16         Assert.notNull(beanDefinition, "Bean definition must not be null");

17         if (containsBeanDefinition(beanName)) {

18             logger.warn("Ignoring bean definition [" + beanDefinition + "] for bean '" + beanName +

19                     "': there's already [" + getBeanDefinition(beanName) + "] bound");

20         } else {

21             super.registerBeanDefinition(beanName, beanDefinition);

22         }

23     }

24

25 }

26 

You can use it as normal ClassPathXmlApplicationContext:

 1         ConfigurableApplicationContext ctx;

 2

 3         ctx = new IgnoringDuplicateBeansClassPathXmlApplicationContext("a.xml");

 4         SomeBean b = (SomeBean) ctx.getBean("xyzBean");

Posted in java, spring | Leave a Comment »

Migrating JUnit + JMock tests to TestNG

Posted by Piotr Gabryanczyk on March 17, 2007

Following QCon presentation of Alexandru Popescu and Cedric Beust on TestNG and TDD I started switching IntellJ Eclipse Dependency Sync plugin to use TestNG.
It was very simple with TestNG IntelliJ plugin which has “Convert JUnit test to TestNG” intention.

JMock integration
One thing I struggled with was JMock integration. Although EasyMock seems to be very popular, many people prefer JMock as it provides more “fluent” interface. I think I am it this camp 🙂

The integration of JMock and TestNG turned out to be very simple:
– test class needs to extend MockObjectTestCase
– make sure that setUp() and tearDown() methods in the super class are called. So you need to override them in your test class and annotate with @BeforeMethod, @AfterMethod.

Here is the example:

  1 public class DependencySynchronizerTest extends JDummyTestCase {
  2
  3     @BeforeMethod public void setUp() throws Exception {
  4         super.setUp();
  5         ...
  6     }
  7
  8     @AfterMethod protected void tearDown() throws Exception {
  9         super.tearDown();
 10     }
 11
 12     @Test public void testTraceChangesUserApprovesLibraryName() {
 13         expectFullRegistrationToBeDone();
 14         dependencySynchronizer.traceChanges(file);
 15     }
 16     ...
 17 }

Posted in intellij, java, testing | 4 Comments »