MyBatis MapperScannerConfigurer to scan base package from classpath - java

I have configured MapperScannerConfigurer in spring application context as follow:
<bean name="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
<property name="basePackage" value="path.to.package.from.classpath.dao" />
</bean>
Here basePackage is in a jar file that is set in classpath.
One of the mapper from the package is autowired in the one of the services I am using. Looks like MyBatis is failing here to scan package from classpath as I am getting error stating no such Bean found:
No qualifying bean of type 'path.to.package.from.classpath.dao.UserMapper' available: expected at least 1 bean which qualifies as autowire candidate.
I have searched online and found nothing which has similar scenario.

I am going to answer here my own question as it may help someone facing the similar issue.
The problem was in the way I created jar in the first place. iBatis might have a different way of scanning the packages as it was working and I thought the same could work with MyBatis. But MyBatis may have a different mechanism for scanning packages. It appears it is looking for directory entries in the jar and if it does not find it, it will throw this exception. So make sure you choose the option Add directory entries while creating the jar as shown below:

Related

java.lang.ClassNotFoundException When Filepath is Correct

I'm working with Spring right now and have been trying to resolve a number of Failed to load ApplicationContext errors. This latest one is because it can't find a specific class when creating a bean structured like the following:
<bean id="problematicBean"
class="com.domain.application.search.problematicBean">
<property name="missingClass">
<bean class="com.domain.application.search.MissingClass">
</bean>
</property>
</bean>
I've triple checked and the filepath used in the bean class is correct. Other beans with identical paths (at least to the point of applicaiton) work perfectly. The file exists exactly where it should be for this classpath to work. The only difference is that this is a groovy file. Does anyone know why my application can't find the class?

Spring and MyBatis cannot find bean via MapperScannerConfigurer if interface inside .jar

I'm using Spring 3.2.0 in a legacy project with Mybatis 3.3.0 and Mybatis Spring 1.2.3.
I have several projects that use this technology and they need to have similar new code added to a library that will allow me to interact with an outside system, and during this interaction I need to call several methods in the database in this new code.
I created an interface and put it in a package, say:
com.mycompany.myapp.dao.MyNewService
That interface has a few methods. All of those are defined in a Mybatis mapper file, MyNewService.xml in that same package path.
I create a .jar file of all this code.
In my main application, I added a dependency to this .jar file and it ends up inside of WEB-INF\lib\MyHelpers.jar
In that application, I have a root application context spring file and I attempt to use a mybatis MapperScannerConfigurer to find this new bean/service via:
<!--scan for mappers and let them be autowired -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.mycompany.myapp.dao" />
<property name="sqlSessionFactoryBeanName"
value="sqlSessionFactory" />
</bean>
When I run this code, it appears that it cannot find this service in that package path which I know is in WEB-INF\lib\MyHelpers.jar.
The application produces a warning on startup:
WARN (ClassPathMapperScanner.java:167) - No MyBatis mapper was
found in '[com.mycompany.myapp.dao]' package.
Please check your configuration.
The code later fails during dependency injection with a massive stacktrace which essentially says:
2017-03-08 15:38:39,625 [[ACTIVE] ExecuteThread: '0' for queue:
'weblogic.kernel.Default (self-tuning)'] ERROR
(org.springframework.web.servlet.DispatcherServlet:466) - Context
initialization failed
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'orderDetailsController': Injection of
autowired dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not
autowire field: private com.mycompany.myapp.dao.MyNewService
com.mycompany.otherapp.controller.OrderDetailsController.myNewService
; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
matching bean of type [com.mycompany.myapp.dao.MyNewService ] 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)}
If I dig into that Mybatis code, its simply not finding the resource from the package path inside that .jar when it's using some ResourceResolver code. IF I move my code into my project directly rather than adding the .jar dependency, the code works fine without error.
The concern of course is that I have to put this same code across six projects, so I thought I'd have it in this .jar file and use the MapperScannerConfigurer. We use that in all the projects but all the .xml is within the applications WEB-INF\classes when deployed, it is not inside a .jar file within WEB-INF\lib.
Any ideas how to accomplish this? In summary, it would be akin to:
Making a file called Model.jar based on Mybatis interfaces and .xml mapper files
Adding this as a dependency that appears in WEB-INF\lib
configuring the main spring applicationContext file using the syntax I have above.
If you need more clarification, I can certainly add it.

gettign proxy of a bean in different project inside java class

I am new to the world of spring so i may ask a silly question but please let me the solution of my below problem please .
My problem is that I have two projects independent project nae is project A and project B ,now in project A i have the below xml configuration of bean
<bean id="abcService" class="com.jmx.JMXServiceImpl" autowire="no">
<constructor-arg index="0">
<ref bean="jobDetailsDomainHome" />
</constructor-arg>
</bean>
now in project A this bean get initilazied easily now i need this same bean initialized in project B also , so i have added project A in project B classpath also now please advise inside java class named rty of Project Bhow can i call this same bean abcService
The bean abcService depends on bean jobDetailsDomainHome. So there's no way to use abcService without the other bean.
You can split the configuration in various xml files. So define the abcService and the needed beans in one xml file, which is imported by the configurations of project A and project B.
<import resource="classpath*:service-context.xml" />
The import of xml files can use the classpath like shown above. But you can use locations in the file system too.
It's not important which bean is defined in which file as long as every needed bean is defined.

BeanNotOfRequiredTypeException: spring factory not being resolved to child type

I'm having an issue with a PropertiesFactoryBean not being resulved to a Properties object in spring. Instead I get the following error:
org.springframework.beans.factory.BeanNotOfRequredTypeException: Bean named 'authProperties' must be of type [java.util.Properties], but was actually of type [org.springframework.beans.factory.config.PropertiesFactoryBean]
at org.springFramework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:367)
at org.springFrameowkr.beans.factory.support.AbstractBeanFactory.etBean(AbstractBeanFactory.java:198]
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1121
at *our code here*
This code was written by others who have used it reliably for some time, so the issue is likely configuration issue rather then bad code. However, the failure occurs on the return line of this method:
private static Properties getPropsFromContext(String context) {
try(AbstractApplicationContext ctx = new ClassPathXmlApplicationContext(context)){
return ctx.getBeans("authProperties", Properties.class));
}
}
The relevant lines of the XML file are:
<bean id="authProperties" class="org.springFramework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="classpath:props/auth.properties" />
</bean>
Ultimately the code is being called from within tomcat. We are using our own RealmBase class for the tomcat Relm, which calls this code. The jar containing our RealmBase class is in the tomcat/lib directory.
What should happen is that spring should recognize that PropertiesFactoryBean implements the FactoryBean interface and it should call getObject of the PropertiesFactoryBean as part of the getObjectForBeanInstance called by doGetBean method, which would return the Properties object. However, for some reason this is not happening, and I'm getting the PropertiesFactoryBean object back instead of the Property being returned. I've even looked through the code to verify this.
Our unit tests of this method run fine, which once again suggests the failure is not with the code, but sometime after it gets compiled, likely a configuration issue with tomcat. As far as I can tell there are no duplicate spring jars in the tomcat classpath or other obvious naming collisions.
I'm using Tomcat6. Our spring jars are mostly 3.2.9, a few 3.1.0, but I think the relevant jars are all 3.2.9
Why would it fail to generate the Property value correctly?
I ultimately discovered I was running an outdated version of the realm jar. When I installed the new Realm things worked correctly. I assume my issue was that the old Realm was compiled to a different version of spring.

Importing Spring beans from other Maven modules inside a WAR?

I have a new web app that is packaged as a WAR as part of a multi-module Maven project. The applicationContext.xml for this WAR references beans that are imported from the "service" module, which in turn imports beans from the "dao" module. The import statement in applicationContext.xml looks like this:
<import resource="classpath*:service.xml" />
and the one inside the service.xml file looks like this:
<import resource="classpath*:dao.xml" />
Neither Spring STS, nor Eclipse show any warnings or errors in my bean files. I reference the imported beans all over the place. The Maven build works fine and the DAO integration tests all pass (they use the beans). I don't have any service integration tests yet.
But when I start up the WAR in Jetty I get an error:
Error creating bean with name 'securityService'
Cannot resolve reference to bean 'userDAO' while setting constructor argument
All of the imported bean XML files can be found inside their respective JAR files in the WEB-INF/lib directory. Indeed, the service bean that threw the error is itself defined inside the service.xml file inside the service module's JAR file.
Apparently the service module can't find the bean that it imported from the dao module. Obviously I don't understand something...seems like this should this Just Work?
I enabled DEBUG logging for 'org.springframework' in order to see if I could learn anything. What I found were messages to the effect that the DAO beans had been created, but there was also a message about them having no name or id.
I check the file, and they all did have an id. So what was it? I check the XML namespace and saw:
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"
and noticed it was old (I am using Spring 3.0.2) and changed it to:
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
Once I changed it, Spring instantly threw half a dozen errors regarding beans that were defined incorrectly (but never used apparently). Once I fixed those errors, everything Just Worked. I've since gone through the entire system checking Spring XML file namespace versions.
Thanks to all for the help. Can't believe I wasted a day on this stupidity!!
The difference between the classpath:thingy.xml and classpath*:thingy.xml notation is that the former uses the standard classpath mechanism to resolve one resource (using ClassLoader.getResource(name)), whereas the latter will use ClassLoader.getResources(name) to retrieve all matching resources on the classpath, a distinction that should be irrelevant in your situation as I guess there is only one dao.xml file on the class path.
I think your problem is different, you are missing a leading slash.
Use this for a single resource
<import resource="classpath:/dao.xml" />
and this for multiple resources
<import resource="classpath*:/dao.xml" />
See
Spring Reference: The classpath*
prefix
Sun JavaDocs: ClassLoader
It should be like
<import resource="classpath:service.xml"/>
Are you having multiple applicationContexts and possibly the parent context is referring to a bean defined in the child context?

Categories

Resources