0

I am having two Service CLass A & B

Class A{

function a1()
{
a2()
}

**@Transactional**
funciton a2(){
a3()
}

function a3(){
   B.b1()
}

}

From Controller I call the function a1() for Service A, from a1() I call the function a2() which has transactional annotation , which then calls a3() which then calls b1() for Service B. Will my transaction work? I mean all the work inside a2(), will be in transaction or not?

Edited

From the comments, I am trying to self invocation but it is not working, I have tried this

@Service(value="TableService")
public class TableService implements Service {

    @Autowired
    private ApplicationContext applicationContext;

    private Service self;

    @PostConstruct
    private void init() {
        self = applicationContext.getBean(TableService.class);
    }
}

But it is giving error

at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) [spring-boot-devtools-1.3.3.RELEASE.jar:1.3.3.RELEASE]
Caused by: org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'TableService' must be of type [com.example.service.TableService], but was actually of type [com.sun.proxy.$Proxy110]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:378) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:220) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:351) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:332) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1066) ~[spring-context-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at com.example.service.TableService.init(TableService.java:26) ~[classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_91]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_91]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_91]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_91]
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:354) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:305) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:133) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    ... 23 common frames omitted

I have also tried this

@Service(value="TableService")
public class TableService implements Service {

    @Resource(name="TableService")
    private Service self;

}

It is giving this error

at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) [spring-boot-devtools-1.3.3.RELEASE.jar:1.3.3.RELEASE]
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.example.service.TableService com.example.web.DemoController.tableService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.example.service.TableService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:573) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    ... 22 common frames omitted
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.example.service.TableService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1373) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1119) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:545) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    ... 24 common frames omitted
Ankit Bansal
  • 2,162
  • 8
  • 42
  • 79
  • 1
    notice the member methods will not obtain the transaction at all without an additional configuration http://stackoverflow.com/questions/3423972/spring-transaction-method-call-by-the-method-within-the-same-class-does-not-wo – WildDev Apr 05 '17 at 06:41
  • So should I move a1 to different class? Also if I move a1 to diff class, then a3 will get transaction or not? Also what is the good way of assigning additional configuration – Ankit Bansal Apr 05 '17 at 06:51
  • yes you've to. Alternatively, you can use the self-injection using `@Resource` annotation or to setup this yourself using `@PostConstruct` one. However, the first option does look better. http://stackoverflow.com/questions/5152686/self-injection-with-spring – WildDev Apr 05 '17 at 07:01
  • I have tried what u said. It is giving some exception while I am trying self injection. I have edited question to add the code & exception. – Ankit Bansal Apr 05 '17 at 09:01
  • actually it's the different issue, it's better to ask it as a dedicated Q. To fix the above there's a sense to omit the `@Service` value param at the last case and then self-inject this as `@Resource(name="tableService")` starting from lowercase – WildDev Apr 05 '17 at 10:37

1 Answers1

1

No it won't as it is an internal method call. Spring uses proxies and as such the @Transactional in this case is pretty much useless.

If this scenario

Class A{

function a1(){
a2()
}

**@Transactional**
function a2(){
B.a3()
}

class B{
 function a3(){
}
}

The answer is yes.By default @Transactional has a propagation of REQUIRED,so a3() will be in transaction .spring doc transaction propagation

Seamas
  • 1,041
  • 7
  • 13
  • No it won't as it is an internal method call. Spring uses proxies and as such the `@Transactional` in this case is pretty much useless. – M. Deinum Apr 05 '17 at 07:17