简体   繁体   中英

How to have a jersey web service class implement interface and be transactional

I would like to use Jersey and Spring to write a java class that is both a web service server-side class and also transactional with spring-tx (so that each web service request either completely finishes its work in the db or completely rolls back its work in the db).

But, when I do that like so...

package com.test.rest

import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

@Component 
@Transactional
public class TestRestService implements TestRestServiceInterface {
    ...
}

the TestRestService class is not registered as a web service class by Spring.

I am using <context:component-scan base-package="com.test.rest"/> in my spring config file to register the web service classes in the com.test.rest package (package name changed for the example).

If I either remove @Transactional or have TestRestService not implement an interface the class is registered by Spring as a web service class and the code works.

Is there a way for me to have both?

I am currently using sprint-tx, spring-jersey and spring-context 3.0.7 and jersey 1.0.3.1

After looking at this a lot I have come to the conclusion that it just will not work (without AspectJ perhaps).

I believe it won't work because of this code in jersey-server-1.0.3.1:com.sun.jersey.api.core.ResourceConfig.java

438  /**
439   * Determine if a class is a root resource class.
440   *
441   * @param c the class.
442   * @return true if the class is a root resource class, otherwise false
443   *         (including if the class is null).
444   */
445  public static boolean isRootResourceClass(Class<?> c) {
446      if (c == null)
447          return false;
448      
449      if (c.isAnnotationPresent(Path.class)) return true;
450  
451      for (Class i : c.getInterfaces())
452          if (i.isAnnotationPresent(Path.class)) return true;
453  
454      return false;
455  }

For some reason, when we have @Transactional on a class that implements an interface the Proxy class generated by spring-tx (whether CGLIB or JDK Dynamic proxy based) doesn't have the @Path annotation so isRootResourceClass returns false and the class is not registered as a web service class. I verified this while debugging through the code.

I guess I am just going to have to choose between implementing an interface or making my web service class transactional (unless I go with AspectJ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM