I have several 'standard' junit integration test with arquillian, tomcat7 embedded (arquillian-tomcat-embedded-7:1.0.0.Final-SNAPSHOT, tomcat-embed-core:7.0.50) and Shrinkwrap.
#RunWith(Arquillian.class)
public class TestMe {
#Deployment
public static WebArchive deploy() {
return
ShrinkWrap.create(WebArchive.class, "test.war")
.addPackages(true, "org.foo")
.addAsManifestResource("META-INF/context.xml", "context.xml")
.addAsWebInfResource("WEB-INF/beans.xml", "beans.xml")
.addAsWebInfResource("WEB-INF/web.xml", "web.xml").as(WebArchive.class);
}
#Test ...
}
Separately executed via maven, every test is green. But if I do a mvn verify and start the whole testsuite I get: java.net.BindException: Address already in use: JVM_Bind :9095. What is the problem?
arquillian.xml:
<arquillian xmlns="http://jboss.org/schema/arquillian"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jboss.org/schema/arquillian http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
<defaultProtocol type="Servlet 3.0" />
<engine>
<property name="deploymentExportPath">target</property>
</engine>
<container qualifier="tomcat" default="true">
<configuration>
<property name="unpackArchive">true</property>
<property name="bindAddress">localhost</property>
<property name="bindHttpPort">9095</property>
<property name="serverName">amgui-arquillian-tomcat7-embedded</property>
</configuration>
</container>
It looks like mvn verify is trying to run tests in parallel. Or at least not waiting for the previous test to clean up before it starts the next one. You can't have more than one process binding to the same address/port combination.
Tomcat connectors support the concept of using a new free port every time they start to avoid these sorts of issues (set the port to zero) but I don't think that on its own will help you. Your test environment would need to know to query Tomcat to find out which port to use for every test.
I'd try and modify your tests so they don't run in parallel.
Related
I am using spring boot 1.5.4 with mybatis-spring 3.1. I am able to successfully run my application via eclipse. But when I used commandline (java -jar jarname), I get below exception. my standalone application is stopping. I want to move my app to deploy to different machine with the jar. Please help.
Caused by: org.apache.ibatis.type.TypeException: Could not resolve type alias 'MyClass'. Cause: java.lang.ClassNotFoundException: Cannot find class: MyCLass
at org.apache.ibatis.type.TypeAliasRegistry.resolveAlias(TypeAliasRegistry.java:120)
at org.apache.ibatis.builder.BaseBuilder.resolveAlias(BaseBuilder.java:149)
at org.apache.ibatis.builder.BaseBuilder.resolveClass(BaseBuilder.java:116)
... 36 more
I resolved the same issue by moving to autoconfigure(using spring properties) I originally had my db configuration(datasource, session factory) configured in a javaconfig class. I'm removed the config and moved my config to my application properties(yml format) ..
Below is what I have
mybatis:
typeAliasesPackage: com.wiredinformatics.preauth.domain
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/preauth?
useSSL=false&serverTimezone=UTC
username: myuser
password: mypass
dbcp2:
driver: com.mysql.cj.jdbc.Driver
initial-size: 2
max-total: 10
max-idle: 10
min-idle: 5
max-wait-millis: 30000
validation-query: SELECT 1
I haven't had time yet to figure out why having my own java config broke the scanning. It worked ok in eclipse, but failed when running from the command line
I solved this problem!
https://github.com/mybatis/mybatipse/issues/77
#deoxyseia
remove
sessionFactoryBean.setTypeAliasesPackage("com.your.packae.pojo")
change resultType="MyClass" to
resultType="com.your.packae.pojo.MyClass"
repackage
I had a similar problem while working in a Maven project, resulting in the same errors.
My situation is that I have a executable jar with Spring Boot which has a nested jar (which uses regular Spring) as dependency. While running in IntelliJ, there was absolutely no problem, due to the way that IntelliJ finds its classes.
While trying to start the jar locally with java -jar jarname.jar so that I could deploy it on a remote server, MyBatis had trouble scanning the typeAliases and typeHandlers packages.
Since I'm working on a legacy-project which mixes Spring Beans initialized in Java and xml, I had one hell of a time determining the root cause. A lot of answers said to change your resultType to the full classpath like this answer. This works. But in my case that would mean hundreds of changes to our DAO's.
Finally, I got on track following this external link from titanwolf.
Here's what you need to do:
add the following dependency to your POM (the jar which contains your MyBatis setup)
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
set the VFS property on your SqlSessionFactoryBean
xml:
<bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory">
<property name="vfs" value="org.mybatis.spring.boot.autoconfigure.SpringBootVFS"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<property name="dataSource" ref="dataSource"/>
</bean>
or if you use regular Java for your bean initalizing:
#Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
factory.setDataSource(dataSource);
factory.setVfs(SpringBootVFS.class);
return factory;
}
And that's it. Works locally and on remote server. Hope I saved anyone else some headaches.
note: mybatis-config.xml contains my configuration including, but not limited to:
<configuration>
<settings>
<setting name="lazyLoadingEnabled" value="false"/>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<typeAliases>
<package name="com.my.path.model"/> <!--wasn't being picked up before fix-->
</typeAliases>
<typeHandlers>
<package name="com.my.path.mybatis"/> <!--wasn't being picked up before fix-->
</typeHandlers>
<mappers>
<mapper resource="sql/my-dao.xml"/>
<mappers>
</configuration>
You can trace your own errors better by enabling logging for MyBatis. Just add the following line to your application.properties file:
logging.level.org.mybatis=DEBUG
I have Arquillian setup in Gradle to spin up a REST server and run some tests against a REST client. Everything works fine, except for the fact that the server hosting the CI already uses port 8080.
I have added the following settings to my build.gradle file
arquillian {
containers {
tomcat {
version = '7'
config = ['bindHttpPort': 18080]
type = 'embedded'
}
}
}
But it has no effect. How can I change the port used by the embedded tomcat 7 container?
EDIT
There is a workaround, which is to have the following in a file called arquillian.xml. Still, it would be nice to have the option of defining the port in the build.gradle file.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<arquillian xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://jboss.org/schema/arquillian"
xsi:schemaLocation="http://jboss.org/schema/arquillian http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
<container qualifier="tomcat" default="true">
<configuration>
<!-- We need to change the port from the default of 8080 because 8080 is quite commonly not available -->
<property name="bindHttpPort">18080</property>
</configuration>
</container>
</arquillian>
I have a small web application in development using Maven, Spring MVC and Spring Data Mongo. I am getting a java.lang.NoSuchMethodError when one of my Controllers attempts to access a method defined in a custom repository. The same method works fine when exercised via a JUnit 4 test extending AbstractJUnit4SpringContextTests and using a near-identical XML configuration file.
Standard repository:
public interface IndividualRepository extends MongoRepository<Individual, String>, IndividualRepositoryCustom {
...
}
Custom interface:
public interface IndividualRepositoryCustom {
Individual findByIdentifier(String identifierType, String identifierValue);
}
Custom implementation:
public class IndividualRepositoryImpl implements IndividualRepositoryCustom {
#Autowired
private MongoTemplate mongoTemplate;
#Override
public Individual findByIdentifier(String identifierType, String identifierValue) {
String locator = String.format("identifiers.%s", identifierType);
return mongoTemplate.findOne(query(where(locator).is(identifierValue)), Individual.class);
}
}
dataaccess-config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/data/mongo
http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd">
<mongo:repositories base-package="com.myco.dataaccess"/>
<mongo:mongo host="mongo.myco.com" port="27017"/>
<mongo:db-factory dbname="test" mongo-ref="mongo"/>
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg ref="mongo"/>
<constructor-arg value="test"/>
</bean>
</beans>
In my JUnit test I have (excerpt):
#Autowired
private IndividualRepository individualRepo;
...
List<Individual> foundList = individualRepo.findAll();
assertNotNull(foundList);
assertTrue(foundList.size() > 0);
Individual found = individualRepo.findByIdentifier("someid", "123456");
assertNotNull(found);
assertEquals("Bob", found.getFirstName());
The test passes fine, calling both findAll() (standard Repository method) and findByIdentifier() (custom method). The latter fails with NoSuchMethodError when called by a Controller running in a web application in Jetty, while the same Controller can call findAll() with no issues.
This turned out to be nothing to do with Spring Data, but an issue with the way I was using the maven-jetty-plugin with my multi-module build.
Basically, I was running mvn jetty:run for my web module which had a dependency on my dataaccess module (where my JUnit tests lived). As I was rebuilding the project with mvn clean package, the latest versions were not being placed in my local repo, and therefore were not being picked up by the mvn jetty:run process running alongside my build process. Problem was solved by building with mvn clean install.
So, as usual, the error message was spot on - the method indeed did not exist in the version of the JAR that Jetty was being supplied.
I'm using a System property to define the location for an environment-specific properties file. However, I would like to override that value to something different for integration tests.
Here's my production spring setup. I'm using a custom PropertyPlaceholderConfigurer to resolve some encrypted property file values, but that's not important here:
<-- Spring configuration in file service-spring-beans.xml -->
<bean class="com.mycompany.MyPropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:properties/${MY_ENVIRONMENT}/${MY_ENVIRONMENT}.properties</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="false"/>
<property name="ignoreUnresolvablePlaceholders" value="true"/>
</bean>
At runtime, we define the value of MY_ENVIRONMENT as a Java system property. This all works as expected. However, for integration tests, I would like to define MY_ENVIRONMENT as "inttest", so the integration-test specific property file properties/inttest/inttest.properties is loaded.
I've tried to use a spring context loaded by the integration-test to set up a String bean with the id MY_ENVIRONMENT:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<context:component-scan base-package="com.mycompany.myclasses"/>
<bean class="java.lang.String" id="MY_ENVIRONMENT">
<constructor-arg value="inttest"/>
</bean>
<!-- this imports the production spring context -->
<import resource="classpath:service-spring-beans.xml"/>
</beans>
However, the value of MY_ENVIRONMENT is not resolved , and I get this error when running the integration tests.
Caused by:
org.springframework.beans.factory.BeanInitializationException: Could
not load properties; nested exception is
java.io.FileNotFoundException: class path resource
[properties/${MY_ENVIRONMENT}/${MY_ENVIRONMENT}.properties] cannot
be opened because it does not exist
How can I override MY_ENVIRONMENT at inttest time without passing a System property to the JVM?
Since I was using the maven surefire plugin to run integration tests, the simplest solution turned out to be setting the system property using the surefire plugin configuration, like this:
<configuration>
<systemPropertyVariables>
<MY_ENVIRONMENT>inttest</MY_ENVIRONMENT>
</systemPropertyVariables>
<!-- ... -->
<configuration>
Since you don't want to use profiles, you can create multiple contexts and just include the proper context files for what you want. So for integration testing you have have your application-context.xml and an integration-property-context.xml file while, in the prod environment you would include the application-context.xml with a production-property-context.xml file. I've seen this approach used heavily to switch datasources between dev and prod where dev would be a BasicDataSource implementation and the prod environment references a JDNI DataSource.
This approach will help you avoid ActiveProfiles, but you run in to the problem of managing duplicate beans possibly which ActiveProfiles really simplified down.
you could look at overriding your whole property placeholder implementation using active profiles. that is, the default (no profile) launches your property placeholder, but a test profile (e.g. 'test') could create a new test bean for the property placeholder.
one of the challenges with property placeholder is that its loaded at the very early stages of the application context startup, so a normal override bean may not work.
<junit printsummary="on" fork="yes" forkmode="once"
haltonerror="false" haltonfailure="false"
failureproperty="junit.failure" showoutput="false" maxmemory="1024m">
<classpath>
<path refid="CLASSPATH_JUNIT"/>
<dirset dir="${TEST_BUILD_DIR}"/>
</classpath>
<batchtest fork="no" todir="${TEST_BUILD_DIR}">
<fileset dir="${COMP_TEST_SRC}">
<include name="**/*Test.java" />
<include name="**/Test*.java" />
<exclude name="**/EswTestCase.java" />
</fileset>
</batchtest>
<formatter type="xml" />
</junit>
this takes lot of time to generate xml report, and it thorws following error:
Caught an exception while logging the end of the build. Exception was:
java.lang.OutOfMemoryError: PermGen space
why it takes long time to genearte xml? how to resolve this error and make application to run fast. I have only max of 10 test files. I use command promt to execute ant script.
Analysis:
1)If i run batch test only for test calss which extends Junit test it execute very fast. eg:
public class ImpactsParserTest extends
TestCase{..
2)Now if i have test class which extends spring junit test as:
public class AddressLookupServiceTest
extends EswTestCase{..
public class EswTestCase extends
AbstractDependencyInjectionSpringContextTests{..
this causes junit target to run very slowly and causes outof memory error. why itis happening like this?
3) when I make batchtest fork="yes" instead of no, then build is quick and doesnt throw outof memory. But, it throws error like:
java.lang.NoClassDefFoundError
at org.apache.log4j.Logger.getLogger(Logger.java:118)
..
java.lang.NoClassDefFoundError: com.bgc.ordering.wizard.back.services.EswTestCase
even though, i have specified these jar file and class file in classpath element as:
and logger jar in
<path id="CLASSPATH_JUNIT">
<fileset dir="${BUILD_LIBS_HOME}">
<include name="*.jar" />
</fileset>
<pathelement location="${TEST_CLASSES_DIR}" />
<pathelement location="${TEST_BUILD_DIR}" />
<pathelement location="${COMP_BUILD}" />
<pathelement location="${COMP_CLASSES}" />
<path location="${APP_DIR}\bgc-esw-services\target\classes"/>
<pathelement location="${APP_DIR}\bgc-esw-web\target\classes" />
...
log4j.properties present at ${TEST_BUILD_DIR}
using: apache-ant-1.8.1 and junit-3.8.1.jar
This error occurs when the JVM runs out of space in the permanent generation heap. The memory in the Virtual Machine is divided into a number of regions. One of these regions is PermGen. It's an area of memory that is used to (among other things) load class files. The size of this memory region is fixed, i.e. it does not change when the VM is running. You can specify the size of this region with a commandline switch: -XX:MaxPermSize. The default is 64 Mb on the Sun VMs. To fix this issue you can give it a higher value like 256mb.
My guess is that you not only run unit tests you also run integration tests e.g. you have a class wired with Spring and you require their dependencies. That's why you have EswTestCase. If you just want to write unit tests I'd recommend you instantiate your class and mock the dependencies to other classes that you are not testing directly. This will minimize your memory footprint because you don't have to create your Spring application context.
This is what the JavaDoc says about AbstractDependencyInjectionSpringContextTests:
Really for integration testing, not
unit testing. You should not normally
use the Spring container for unit
tests: simply populate your POJOs in
plain JUnit tests!
As of Spring 3.0, the legacy JUnit 3.8 base class hierarchy (i.e., AbstractDependencyInjectionSpringContextTests, AbstractTransactionalDataSourceSpringContextTests, etc.) is officially deprecated and will be removed in a later release. It is recommended that you use the Spring TestContext Framework for writing integration tests. Instead of extending EswTestCase with AbstractDependencyInjectionSpringContextTests you should use the annotations.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration
public class EswTestCase
{
...
}