Sample spring mvc application to see exception with spring integration

106 views
Skip to first unread message

Alex

unread,
Sep 18, 2013, 5:23:23 AM9/18/13
to geda-generic-dto-asse...@googlegroups.com
Hi,
I just start a new topic to be able to attach an example - this is a web application that can be built with using Maven, and the war file, once placed under tomcat/webapps produces exception on tomcat startup.

My Tomcat version is 7.0.41

Regards,
Alex
sample.zip

Denis Pavlov

unread,
Sep 18, 2013, 8:27:42 AM9/18/13
to geda-generic-dto-asse...@googlegroups.com
Hi Alex,

I had a look at the code you have uploaded and found 2 things:
1. You have excluded javassist from GeDA core dependency - that cannot work because javassist is used by default method synthesizer (its the class that generates fast copy pipes for fields and it uses javassist to self generate during runtime). Without it GeDA simply will not work (at least for spring-integration module). If you have issues with javassist you can use bcel as alternative but this is not part of spring-integration unfortunately and you will need to use the core only. <-- this issue however has nothing to do with the error (but it does appear when you fix the original issue, see point 2)

Full dependencies: 
        <dependency>
            <groupId>com.inspire-software.lib.dto.geda</groupId>
            <artifactId>geda.core</artifactId>
            <version>3.1.0</version>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.bcel</groupId>
                    <artifactId>bcel</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.8.0.GA</version>
        </dependency>
        <dependency>
            <groupId>com.inspire-software.lib.dto.geda</groupId>
            <artifactId>geda.spring-integration</artifactId>
            <version>3.1.0</version>
        </dependency>
    </dependencies>



2. You are using com.fasterxml.jackson.databind.ObjectMapper - which is class. In order to use GeDA spring @Transferable annotation all classes get auto proxied - this is how Spring AOP works. So what you get is a proxy over the com.fasterxml.jackson.databind.ObjectMapper and Spring cannot determine what type of object it is and therefore you get this message - 
java.lang.IllegalArgumentException: Can not set com.fasterxml.jackson.databind.ObjectMapper field com.example.test.web.controller.HomeController.objectMapper to com.sun.proxy.$Proxy17
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:146) ~[na:1.6.0_51]
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:150) ~[na:1.6.0_51]
at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:63) ~[na:1.6.0_51]

which reads that for field HomeController.objectMapper Spring cannot set object $Proxy17 (which is the proxied ObjectMapper). Therefore you get this error. If you create a wrapper Service with an interface that delegates all methods to ObjectMapper objects inside it.

class MyObjectMapperServiceImpl implements MyObjectMapperService {

   private ObjectMapper obj = new ObjectMapper();

  ... methods ...

}

then I think it will work fine.

Generally, it is not a good idea to have beans made from classes - you should use interfaces for every bean - then Spring AOP works fine.


I also attached the sample-log.txt that shows that all starts working after these modifications and page source for the generated home.html (this is just a proof that it works).

Hope this helps.
sample-log.txt
home.html

Alex

unread,
Sep 18, 2013, 9:22:37 AM9/18/13
to geda-generic-dto-asse...@googlegroups.com
Hi Denis,
thanks  for your help - I'm gonna check it later but it looks like your solution should work. With regards to your comments:
1) My bad, this is a sample project copied from the original project where javaassist is present as part of another dependency, it is excluded just because Maven magically takes the wrong version.

2) Indeed it seems to be the reason, However it is quite common that the third party libraries provide classes that I would like to utilize as Spring beans and it is not convenient to wrap them into services. And btw Hibernate proxies work just fine in my project without any issues. I'm just curious why ALL the classes are auto-proxied when @Transferrable annotation is used? It seems to be not optimal solution.

Thanks
Alex

Denis Pavlov

unread,
Sep 18, 2013, 9:40:41 AM9/18/13
to geda-generic-dto-asse...@googlegroups.com
Hi Alex,

Hibernate proxies are not managed by Spring - hence no issue there. The error is when the context gets created by Spring. Basically they try to be thorough and check the dependencies using isAssignableFrom(). When the class gets proxied by java proxy only interfaces are visible, so when it wraps a class that does not implement interface it is just #ProxyXXX which is not assignableFrom.

Regarding Spring AOP - it is not optimal but a lot of people use it without event knowing about it. I mean not in GeDA but Spring in general. You'll be surprised how many people simply do not look "under the hood" of Spring - there is a lot happening there.

@Transactional works through AOP - which means that Spring wraps all beans so that it can give methods "advice" - in GeDA instance it is the "dto assembly process" advice. Without this proxy there is no way to inject this logic. And there is no way to tell which classes have @Transactional unless you proxify them. So it just how it is, unfortunatelly. I do realise this is not optimal and that is exactly why we have xml-driven strategy that I mentioned in another thread. Also detailed discussion on two approaches (and the dilemma of optimal code) is here: http://www.inspire-software.com/confluence/display/GeDA/Spring+API and here: http://www.inspire-software.com/confluence/display/GeDA/Spring+3+AOP+finetuning

Hope this helps

Alex

unread,
Sep 18, 2013, 10:12:11 AM9/18/13
to geda-generic-dto-asse...@googlegroups.com
Indeed, you are right. But why don't you introduce an annotation for classes that provide @Transferable annotations on methods, auto-scan them on context startup and then proxy?

Regards,
Alex

Denis Pavlov

unread,
Sep 18, 2013, 6:08:00 PM9/18/13
to geda-generic-dto-asse...@googlegroups.com
GEDA-59

I guess I will review the whole spring integration for 3.2.0 + need to migrate to new version anyway.
Reply all
Reply to author
Forward
0 new messages