Reputation: 182
Description of Issue
I have a Spring Boot
Java
application which uses MyBatis
Mappers
that talk to DB2
through the use of interfaces
with XML
.
This set up works properly when running as a Spring Boot
application in the Eclipse IDE
. However, when I use Mavan
to build the application as a WAR
file, and deploy it on an external Tomcat
server, suddenly I receive errors that my mappers cannot be found when the application deploys:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'springmapper': Unsatisfied dependency expressed through field 'thingTypes'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'otherthingtypes': Invocation of init method failed; nested exception is
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.myapplicaton.dao.MybatisMapper.selectByExample
I get the feeling that, when running as a WAR
, the app is no longer scanning these MyBatis
mappers
as mappers
. I must need to change some configuration, but I can't figure out what.
====================
Current Configuration (Works when running on Eclipse IDE
as Spring Boot
app)..
(1) All MyBatis
java
mappers in com.myapplicaton.dao have the @Mapper
annotation:
package com.myapplicaton.dao;
@Mapper
public interface MybatisMapper {
List<Thing> selectByExample(ThingExample example);
//...
}
(2) Added a MapperScan
to the application startup..
@SpringBootApplication
@MapperScan({"com.myapplicaton.dao","com.myapplicaton.other.mappers"})
public class MyApplication extends SpringBootServletInitializer
{
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
(3) Use the MyBatis
Mappers in @Autowired
classes:
@Configuration
public class SomeConfig {
@Bean(name = "springmapper")
@Scope(value = "singleton")
public SpringMapper getSpringMapper() {
return new SpringMapper();
}
@Bean(name = "thingTypes")
@Scope(value = "singleton")
public ThingTypes thingTypes() {
return new ThingTypes();
}
}
package com.myapplicaton.other.mappers;
public class SpringMapper {
@Autowired
ThingTypes thingTypes;
//...
}
package com.myapplicaton.beans;
public class ThingTypes {
@Autowired
MybatisMapper mybatisMapper;
//...
}
====================
Question
Why doesn't this work when deployed as a WAR
?
Upvotes: 0
Views: 1273
Reputation: 182
Alright, after messing with this all day, I sort of have an answer.
Firstly, I had to remove two 'problem' beans I had which used @PostConstruct
on an init()
method which used an @Autowired
Mybatis
mapper. I don't know why it didn't like that, but I don't care because after I removed them, the application booted properly as a WAR
.. mostly.
It used to do something like this:
package com.myapplicaton.beans;
public class ThingTypes {
@Autowired
MybatisMapper mybatisMapper;
@PostConstruct
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
private void init() {
mybatisMapper.selectByExample(example);
}
}
The second issue I had was that the application could not find the MyBatis
mapper
.xml
files in my dao
package when deployed as a WAR
. It was fine when run on Eclipse, as per usual.
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.myapplicaton.dao.MybatisMapper.selectByExample
I checked the WAR
file, and lo and behold, the .xml
files had been skipped by Maven
and only the Java
class
files lived in that folder. I couldn't figure out how to unskip .xml
files with spring-boot-maven-plugin
, and I wasn't about to try to figure out another plugin, so I was able to beat the system as follows:
I created a set of folders in the src/main/resources/
folder of the app with exactly the same folder structure as where the .java
interface
mappers
were located. So, I created src/main/resources/com/myapplication/dao
. I put all of the .xml
files in there.
Upon checking the new WAR, the .xml
files were placed into the same directory as the java
class
files, and MyBatis
worked properly.
Hurrah.
Upvotes: 1