When I execute the following I get a strange error:
"junit.framework.AssertionFailedError: No tests found in com.ac.spring.login.LoginServiceTest
I am using spring 3.0 with junit 4.x.
Test class:
#ContextConfiguration(locations={"classpath:META-INF/spring-context.xml","classpath:META-INF/spring-context-test.xml"})
public class LoginServiceTest extends AbstractJUnit4SpringContextTests{
#Autowired
private LoginServiceTestCase loginTestCase;
#Before
public void setup() {
loginTestCase.initialize();
}
#After
public void teardown() {
}
#Test
public void testLoginWithValidAccount() throws Exception {
loginTestCase.setTestName("Validate Login with valid credentials");
loginTestCase.setTestCondition(loginTestCase.CONDITION_USERNAME, "...");
loginTestCase.setTestCondition(loginTestCase.CONDITION_PASSWORD, "...");
loginTestCase.setExpectedResult(loginTestCase.RESULT_IS_ERROR, false);
assertTrue(loginTestCase.isTestPass());
}
....
}
Case to be tested:
public class LoginServiceTestCase extends TestCase{
#Autowired
private LoginService loginService; // the class to be tested
......
protected void executeTest() throws Exception {
try {
..... } catch (Exception e) {
isError = true;
}
}
build.xml:
<target name="compile" >
<echo message="-----> Compile Classes from ${src}" />
<mkdir dir="${build}/classes" />
<javac srcdir="${src}"
includes="**/*.java"
destdir="${build}/classes"
debug="on">
<classpath refid="dependencies"/>
</javac>
<copy todir="${build}/classes/META-INF">
<fileset dir="${basedir}/config" includes="**"/>
</copy>
</target>
<target name="batch-test" >
<mkdir dir="${reports.tests}"/>
<junit printsummary="yes" haltonfailure="yes">
<classpath>
<pathelement location="${build}/classes"/>
<path refid="dependencies"/>
</classpath>
<formatter type="plain"/>
<formatter type="xml"/>
<batchtest fork="yes" todir="${reports.tests}">
<fileset dir="${src}">
<include name="**/*Test.java"/>
</fileset>
</batchtest>
</junit>
</target>
Where am I going wrong?
Wanted to close this question - but just wanted to inform the problem was with the ant version.Moving up from ant 1.5 to 1.7 took care of the issue.
Related
We have an example WSDL that has been provided by an API provider and we want to integrate with it.
I tried the provided example at https://spring.io/guides/gs/consuming-web-service/ and some other .wsdl files and it all looks good.
In my case with my wsdl - when running the command to generate the classes - only some of them are generated, but not all of them.
This is not the case in SoapUI - all is good there.
Any info why this is happening?
My pom.xml is the following
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.13.2</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<generatePackage>com.test.xxx.soapclient.generated</generatePackage>
<generateDirectory>${project.basedir}/src/main/java</generateDirectory>
<schemaDirectory>${project.basedir}/src/main/resources/wsdl</schemaDirectory>
<schemaIncludes>
<include>*.wsdl</include>
</schemaIncludes>
</configuration>
</plugin>
</plugins>
</build>
What i have come to see is that only the complex types are being created as classes - while the others are not.
In my example the input message is the one below and no classes are being generated for it.
How can i do that?
Also what is interesting here is - soapAction has empty string as parameter - and Java's API requires SoapAction
Java Code
public Object callWebService(String action, Object request){
return getWebServiceTemplate().marshalSendAndReceive(request,new SoapActionCallback(action));
}
Actual WSDL File
<operation name="login" parameterOrder="user password">
<input message="tns:CardManagementEP_login"> </input>
<output message="tns:CardManagementEP_loginResponse"> </output>
</operation>
<message name="CardManagementEP_loginResponse">
<part name="result" type="xsd:string"> </part>
</message>
<message name="CardManagementEP_login">
<part name="user" type="xsd:string"> </part>
<part name="password" type="xsd:string"> </part>
</message>
<operation name="login">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal" namespace="http://com.tch.cards.service"/>
</input>
<output>
<soap:body use="literal" namespace="http://com.tch.cards.service"/>
</output>
</operation>
I managed to resolve the issue with the help of DaShaun Carter from the show Spring Office Hours.
The issue was that the above mentioned WSDL file was really old, so the classes for requests/responses which are not complex were not generated.
What we did is modify the existing WSDL and create these things as complex types - so Jaxb will generate classes for them
example-wsdl.wsdl
<complexType name="login">
<sequence>
<element name="user" type="string"/>
<element name="password" type="string"/>
</sequence>
</complexType>
<complexType name="loginResponse">
<sequence>
<element name="result" type="string"/>
</sequence>
</complexType>
After that, the classes are getting generated, but they did not work for me, and i had to some manual changes in order to get them working
LoginResponse.java
import javax.xml.bind.annotation.*;
#XmlRootElement(name = "loginResponse", namespace = "http://com.tch.cards.service")
#XmlAccessorType(XmlAccessType.FIELD)
public class LoginResponse {
#XmlElement(required = true)
protected String result;
public String getResult() {
return result;
}
public void setResult(String value) {
this.result = value;
}
}
Login
import javax.xml.bind.annotation.*;
#XmlRootElement(name = "login", namespace = "http://com.tch.cards.service")
#XmlAccessorType(XmlAccessType.FIELD)
public class Login {
#XmlElement(required = true)
protected String user;
#XmlElement(required = true)
protected String password;
public String getUser() {
return user;
}
public void setUser(String value) {
this.user = value;
}
public String getPassword() {
return password;
}
public void setPassword(String value) {
this.password = value;
}
}
Also, in my case, the Soap Action did not matter, and i am passing empty strings.
The code where the actual calls were happening is as follows:
Login login = new Login();
login.setUser("user");
login.setPassword("password");
LoginResponse response = (LoginResponse) soapConnector.callWebService("", login);
System.out.println(response);
IMPORTANT NOTE: Change the namespace as per usecase - this is really important
While Spring 4 Rest application loading , i am getting the logger information ( log file name / path / archival days) from database and passing this value to Logj plugin , so that i can retrieve the value from log4j.xml.
My application log file not created and plugin not called ! not getting any error in console as well.
What should i do , for Logj plugin load and log file creation ?
Spring:4.3.15.RELEASE
log4j:2.4.1
java:1.8
SpringWebInitializer.java
public class SpringWebInitializer implements WebApplicationInitializer{
#Override
public void onStartup(ServletContext ctx) throws ServletException {
AnnotationConfigWebApplicationContext webCtx = new AnnotationConfigWebApplicationContext();
webCtx.register(WebConfiguration.class);
webCtx.setServletContext(ctx);
ServletRegistration.Dynamic servlet = ctx.addServlet("dispatcher", new DispatcherServlet(webCtx));
servlet.setLoadOnStartup(1);
servlet.addMapping("/");
//Add Listener.
ctx.addListener(new MyAppContextListner());
}
}
WebConfiguration.java
#EnableWebMvc
#Configuration
#ComponentScan(basePackages ="org.vasa.ws.myapp")
public class WebConfiguration {
}
MyAppContextListner.java
public class MyAppContextListner implements ServletContextListener{
private static final Logger LOGGER = LogManager.getLogger(BenefitsCompositeContextListner.class);
private WebApplicationContext webApplicationContext = null;
#Override
public void contextInitialized(ServletContextEvent event) {
// Database connectivity and get the logger information from db.
}
#Override
public void contextDestroyed(ServletContextEvent event) {
// TODO Auto-generated method stub
}
}
Given below Log4j Plugin i am using
MyLog4JConfigDatabaseLookup.java
#Plugin(name = "MyAppdbLookup", category = StrLookup.CATEGORY)
public class MyLog4JConfigDatabaseLookup extends AbstractLookup {
public String lookup(final LogEvent event, final String key) {
System.out.println("Lookup......");
}
}
log4j2.xml
<Configuration packages="org.vasa.ws.myapp">
<Properties>
<Property name="app-name">MyAppdbLookup</Property>
<Property name="file-level">${MyAppdbLookup:logLevel}</Property>
<Property name="log-file">${MyAppdbLookup:logFile}</Property>
<Property name="log-file-level">${MyAppdbLookup:logLevel}</Property>
<Property name="log-path">${MyAppdbLookup:logPath}</Property>
<Property name="archive-days">${MyAppdbLookup:archive-days}</Property>
</Properties>
<Appenders>
<Routing name="route-log">
<Routes pattern="framework">
<Route key="benefitCompositeWS">
<RollingFile name="message-log" fileName="${log-path}/myapp.log"
filePattern="${log-path}/$${date:yyyy-MM}/myapp.%d{MM-dd-yyyy}-%i.log.gz" append="true">
<PatternLayout
pattern="%d{MM/dd/yyyy HH:mm:ss.SSS z} [%t] %-5level %logger{36} - %msg%n" />
<Policies>
<TimeBasedTriggeringPolicy />
<SizeBasedTriggeringPolicy size="150 MB" />
</Policies>
<DefaultRolloverStrategy max="1000">
<Delete basePath="${log-path}" maxDepth="2">
<IfFileName glob="*/myapp*.log.gz" />
<IfLastModified age="${archive-days}" />
</Delete>
</DefaultRolloverStrategy>
</RollingFile >
</Route>
</Routes>
</Routing>
<Loggers>
<Root level="${file-level}" additivity="false">
<AppenderRef ref="route-log" />
<AppenderRef ref="STDOUT" />
</Root>
</Loggers>
</Configuration>
I have changed my plugin name as lower case and now it's working fine as expected:
#Plugin(name="myappdblookup")
When I ran the Test Class(CountryMapperTest.java), the error has been occurred. The following is error information.
org.apache.ibatis.exceptions.PersistenceException:
### Error building SqlSession.
### The error may exist in tk.mybatis.simple.mapper.CountryMapper.xml
### Cause: org.apache.ibatis.builder.BuilderException:
Error parsing SQL Mapper Configuration.
Cause: java.io.IOException:
Could not find resource tk.mybatis.simple.mapper.CountryMapper.xml
Project Directory
By analysing the error messages, I think that the bug comes from the following statement in the mybatis-config.xml file.
<mappers>
<mapper resource="tk.mybatis.simple.mapper.CountryMapper.xml"/>
</mappers>
I have tried some solutions that work for others:
File | Invalidate Caches / Restart
Select the Directory | Make Directory as Resources Root, etc..
Add the relative code snippet in the pom.xml:
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
Relative code
CountryMapperTest.java
package tk.mybatis.simple.mapper;
import java.io.IOException;
import java.io.Reader;
import java.util.List;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.BeforeClass;
import org.junit.Test;
import tk.mybatis.simple.model.Country;
public class CountryMapperTest {
private static SqlSessionFactory sqlSessionFactory;
#BeforeClass
public static void init() {
try {
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
System.out.println("Test1");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
System.out.println("Test2");
reader.close();
} catch (IOException ignore) {
ignore.printStackTrace();
}
}
#Test
public void testSelectAll() {
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
List<Country> countryList = sqlSession.selectList("selectAll");
printCountryList(countryList);
} finally {
sqlSession.close();
}
}
private void printCountryList(List<Country> countryList) {
for (Country country : countryList) {
System.out.printf("%-4d%4s%4s\n", country.getId(), country.getCountryname(), country.getCountrycode());
}
}
}
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
<typeAliases>
<package name="tk.mybatis.simple.model"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">
<property name="" value=""/>
</transactionManager>
<dataSource type="UNPOOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="12345"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="tk.mybatis.simple.mapper.CountryMapper.xml"/>
</mappers>
</configuration>
CountryMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="tk.mybatis.simple.mapper.CountryMapper">
<select id="selectAll" resultType="Country">
select id,countryname,countrycode from country
</select>
</mapper>
I expect to query the database and show data in console.
More Details
IDE: IntelliJ IDEA, 2019.1
OS: macOS Mojave, 10.14.3
The mapper resource path should be separated by slash.
<mapper resource="tk/mybatis/simple/mapper/CountryMapper.xml"/>
http://www.mybatis.org/mybatis-3/configuration.html#mappers
In addition to the ave's solution, we also need to check the package naming and path.
Because the optical package naming is the same in IntelliJ IDEA, the both are the tk.mybatis.simple.mapper.
Actually, correct path is tk/mybatis/simple/mapper, error path is tk.mybatis.simple.mapper.
Please follow the below method to check it:
File | Project Structure...
click Modules | Your Project Name | Sources
I am new in using maven, I am having a java class as follow:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class DecoupledDataReaderClient {
private IReader reader = null;
private ApplicationContext ctx = null;
public DecoupledDataReaderClient() {
ctx = new ClassPathXmlApplicationContext("basics-reader-beans.xml");
}
private String fetchData() {
reader = (IReader) ctx.getBean("reader");
return reader.read();
}
public static void main(String[] args) {
DecoupledDataReaderClient client = new DecoupledDataReaderClient();
System.out.println("Example 1.3: Got data: " + client.fetchData());
}
}
I am having an ant built file as follow:
<target name="init">
<artifact:dependencies pathId="dependency.classpath">
<dependency
groupId="org.springframework"
artifactId="spring-context"
version="3.2.1.RELEASE"
/>
</artifact:dependencies>
</target>
<target name="compile" depends="init">
<mkdir dir="classes"/>
<javac srcdir="${src}" destdir="${dest}" includeantruntime="false">
</javac>
</target>
<target name="jar" depends="compile">
<mkdir dir="${build}"/>
<jar destfile="${jar}" basedir="${dest}">
<manifest>
<attribute name="Main-Class" value="src.DecoupledDataReaderClient"/>
</manifest>
</jar>
</target>
<target name="run" depends="jar">
<java jar="${jar}" fork="true"/>
</target>
When I run the ant built file I get the error:
error: package org.springframework.context does not exist
error: package org.springframework.context.support does not exist
Is there anything else I have to include in my ant file to make it run?
I would like to run parallel selenium tests (using webriver and the Spring JUnit runner). Webdriver is a spring bean with the custom thread scope. But I get a following warning SimpleThreadScope does not support descruction callbacks So the browsers are not closed. Any idea how to close them (more precisely call the quit method)?
spring config
<bean id="threadScope" class="org.springframework.context.support.SimpleThreadScope" />
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="thread" value-ref="threadScope" />
</map>
</property>
</bean>
<bean id="webDriver" class="org.openqa.selenium.remote.RemoteWebDriver" scope="thread" destroy-method="quit">
<constructor-arg name="remoteAddress" value="http://localhost:4444/wd/hub" />
<constructor-arg name="desiredCapabilities" ref="browserAgent" />
</bean>
maven config
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.12</version>
<configuration>
<includes>
<include>**/*Test.class</include>
</includes>
<reportsDirectory>${basedir}/target/surefire-reports</reportsDirectory>
<parallel>classes</parallel>
<threadCount>2</threadCount>
<perCoreThreadCount>false</perCoreThreadCount>
</configuration>
</plugin>
This post http://www.springbyexample.org/examples/custom-thread-scope-module-code-example.html suggests a custom Thread implementations. But where is an extension point type of Runnable using any JUnit runner?
public class ThreadScopeRunnable implements Runnable {
protected Runnable target = null;
/**
* Constructor
*/
public ThreadScopeRunnable(Runnable target) {
this.target = target;
}
/**
* Runs <code>Runnable</code> target and
* then afterword processes thread scope
* destruction callbacks.
*/
public final void run() {
try {
target.run();
} finally {
ThreadScopeContextHolder.currentThreadScopeAttributes().clear();
}
}
}
Here there is a workaround, not perfect solution, because it blocks browsers until the end of all tests.
You have to create a register of thread scope beans which handles their destruction.
public class BeanRegister {
private Set<CustomWebDriver> beans= new HashSet<CustomWebDriver>();
public void register(CustomWebDriver bean) {
beans.add(bean);
}
#PreDestroy
public void clean() {
for (CustomWebDriver bean : beans) {
bean.quit();
}
}
}
Config it as singleton.
<bean class="BeanRegister" />
You have to write a class extending RemoteWebDriver.
public class CustomWebDriver extends RemoteWebDriver {
#Autowired
private BeanRegister beanRegister;
#PreConstruct
public void init() {
beanRegister.register(this);
}
}
That's it.