Am trying to deploy a war file built with Spring Boot to standalone Jetty webapps folder and start Jetty. During Spring context initialization, I see exceptions:
Caused by:
org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:135)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:476)
Below is my gradle dependency list:
dependencies {
compile(
"org.springframework.boot:spring-boot-starter-actuator:1.1.4.RELEASE",
"org.springframework.security:spring-security-web:3.2.3.RELEASE",
"org.springframework.security:spring-security-config:3.2.3.RELEASE",
'javax.validation:validation-api:1.0.0.GA',
'org.hibernate:hibernate-validator:4.0.0.GA',
"org.codehaus.groovy:groovy-all:2.1.1",
'com.google.code.gson:gson:2.2.1',
"javax.servlet:javax.servlet-api:3.1.0",
"com.sun.jersey:jersey-server:1.16",
"com.sun.jersey:jersey-client:1.16",
"com.sun.jersey:jersey-core:1.16",
"com.fasterxml.jackson.jaxrs:jackson-jaxrs-providers:2.3.2",
"com.sun.jersey:jersey-servlet:1.16",
"com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:2.3.2",
"com.sun.jersey.contribs:jersey-spring:1.16",
"org.springframework:spring-beans:4.0.6.RELEASE",
'com.wordnik:swagger-jersey-jaxrs_2.10:1.3.5',
'com.fasterxml.jackson.core:jackson-core:2.3.0',
"org.springframework:spring-web:4.0.6.RELEASE",
"org.springframework:spring-core:4.0.6.RELEASE",
"org.springframework:spring-tx:4.0.6.RELEASE",
"org.springframework:spring-expression:4.0.6.RELEASE",
"org.springframework:spring-webmvc:4.0.6.RELEASE",
"org.springframework:spring-context:4.0.6.RELEASE",
"org.jasypt:jasypt-spring3:1.9.1",
"com.sun.jersey.contribs:jersey-multipart:1.16",
"org.aspectj:aspectjweaver:1.7.4",
"org.springframework:spring-aspects:4.0.6.RELEASE",
"org.springframework:spring-aop:4.0.6.RELEASE",
'javax.validation:validation-api:1.0.0.GA',
'org.hibernate:hibernate-validator:4.0.0.GA'
)
compile ("org.springframework.boot:spring-boot-starter-web:1.1.4.RELEASE") {
exclude module:'spring-boot-starter-tomcat'
}
I am using ApplicationInitializer class as suggested in Spring Boot docs. What am I missing? How to get past this exception? I have Jetty 9.x server.
class ApplicationInitializer extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
Properties props = getPropertiesFromArgs()
return new SpringApplicationBuilder([Application, "classpath:/META-INF/com/foo/testapp/bootstrap.xml"] as Object[])
.properties(props)
}
Found the issue. initializer class was creating a new application builder instead of using the input parameter. Changing it to below worked fine.
class ApplicationInitializer extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
Properties props = getPropertiesFromArgs()
return application.sources([Application, "classpath:/META-INF/com/foo/testapp/bootstrap.xml"] as Object[])
.properties(props)
}
Related
I have annotated spring boot application with Feign Client
#SpringBootApplication
#EnableFeignClients({"com.ms.Foo1.api", "com.ms.Foo2.api",
"com.ms.Foo3.api", "com.ms.Foo4.api", "com.ms.Foo5.api", "com.ms.Foo6.api",
"com.ms.Foo7.api", "com.ms.Foo8.api", "com.ms.Foo9.api", "com.ms.Foo10.api"})
public class AnalyticsApplication extends SpringBootServletInitializer {
}
everything working fine, AS I just modify the bases packages. its start scanning package outside the api.
#SpringBootApplication
#EnableFeignClients({"com.ms.*.api"})
public class AnalyticsApplication extends SpringBootServletInitializer {
}
I am expecting that #EnableFeignClients({"com.ms.*.api"}) will scan only clients inside the api but it start scanning outside the api package as well.
what I need to change ? or can we apply regex here instead of mention every package ?
You can use a regex filter on #ComponentScan like this:
#ComponentScan(basePackages = "com.ms",
includeFilters = #Filter(type = FilterType.REGEX, pattern="com.ms.*.api"))
public class AnalyticsApplication extends SpringBootServletInitializer {
}
But #EnableFeignClients haven't this feature. The only thing you can do is:
#EnableFeignClients(basePackages = "com.ms")
public class AnalyticsApplication extends SpringBootServletInitializer {
}
com.mohendra.user
server
Application.class //Main class
package2
package3
domain
Campaigns.class
SmsDomainPackage.class
repository
CampaignRepository.class
The above is my folder structure, I am tryring to test CampaignRepository using spring dataJpaTest ,
I have written the following test
#ComponentScan(basePackages = "com.mohendra.user")
#EntityScan(basePackageClasses = SmsDomainPackage.class)
#RunWith(SpringRunner.class)
#SpringBootTest(classes = Application.class)
#DataJpaTest
#RestClientTest
public class CampaignRepositoryTest {
#Autowired
private TestEntityManager entityManager;
#Autowired
private CampaignRepository repository;
#Before
public void setUp() throws Exception {
}
#Test
public void findByCode() {
Campaigns campaigns = new Campaigns();
campaigns.setName("Name");
campaigns.setCode("HELP123");
campaigns.setStartDate(new Date());
campaigns.setEndDate(new Date());
this.entityManager.persist(campaigns);
Campaigns campaigns1 = repository.findByCode("HELP123");
System.out.println();
}
}
The test gives an exception of
java.lang.IllegalArgumentException: Unknown entity:
com.mohendra.user.package3.domain.Campaigns
I have also used #ComponentScan as you can see, and I've also used #EntityScan to try scan entities from packages, but both of them dont work.
I cannot change my folder structure to make it standard, as it is not my project. Is there a solution to it?
The Application class should be in the root package. That way you will not need any #CompontenScan or #EntityScan because Spring Boot scans everything below your root package
Therefor I recomment to put Application.class in the package com.mohendra.user
And you have to decide which test slice you want. You have three:
#SpringBootTest(classes = Application.class)
#DataJpaTest
#RestClientTest
But I assume that you only want #DataJpaTest
I have a spring boot commandline app:
#SpringBootApplication
public class TheApplication implements CommandLineRunner {
public void run(String... args) throws Exception {
...
}
}
and I'd like to test a #Service that TheApplication uses. Normally this is fine if it's an mvc app where TheApplication does not have any functionality but in this case it's a CommandLineRunner and every time I want to test a #Service, run is called, creating a problem with the tests. I need to annotate the test as the #Service uses #Value to configure itself but these annotations cause the application to start and the run method to be invoked.
Is there a way to run a spring boot test:
#RunWith(SpringRunner.class)
#SpringBootTest
public class AccessTokenTest {
...
}
without TheApplication::run being invoked?
Turns out it's fairly easy according to this answer.
#Configuration
#ComponentScan(excludeFilters = #ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = CommandLineRunner.class))
#EnableAutoConfiguration
public class TestApplicationConfiguration {
}
#RunWith(SpringRunner.class)
#SpringBootTest(classes = TestApplicationConfiguration.class)
public class TheTest {
#Autowired
TheService theService;
...
}
I am using WebSphere Liberty 8.5.5 server and writing some batch test cases on this server. I am trying to mock jndi lookup object for testing but while setting up dataSource object in test case I am getting below error, Does anyone know how to set INITIAL_CONTEXT_FACTORY
ERROR : javax.naming.NoInitialContextException: Need to specify class name in environment or system prop
erty, or as an applet parameter, or in an application resource file: java.naming.factory.initial
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:662)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:307)
at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:344)
at javax.naming.InitialContext.lookup(InitialContext.java:411)
You need to set the class name of your initial context factory in the environment of the InitialContext constructor.
For example:
Hashtable<Object, Object> env = new Hashtable<>();
env.put(InitialContext.INITIAL_CONTEXT_FACTORY, "com.example.MockICF");
new InitialContext(env);
Where com.example.MockICF might be written as:
public class MockICF implements InitialContextFactory {
private static Context ctx = new Mockery().mock(Context.class);
#Override
public Context getInitialContext(Hashtable<?, ?> environment) throws NamingException {
return ctx;
}
}
I have some EJBs as JAX-WS Web Service:
#WebService
#Stateless
#Remote(MobileFacade.class)
public class MobileFacadeBean implements MobileFacade {
...
#Resource
WebServiceContext wsc;
...
}
Within this Web Service class, a WebServiceContext is injected via #Resource. I use this WebServiceContext to get the principal in the implementation. This works quite well, but now I wonder how to (Unit-)test this class!
So far, I was using OpenEJB to test my EJBs. Since the Web Service class also is an Stateless Session Bean, I would really like to use the same approach here. However, it does not work that easy - of course, it complains that there is no WebServiceContext when not called as a Web Service.
So the first question is: are there any ways to mock the WebServiceContext in OpenEJB?
And if no, what approach would you favour to test this kind of Web Service classes?
Cheers,
Frank
There are a handful of #WebService unit test examples in the OpenEJB examples zip file. Everything you want should work fine.
simple-webservice
webservice-attachments
webservice-security
webservice-ws-security
The webservice-security example sounds exactly like what you want. The version online uses #RolesAllowed to make the container do the security check rather than doing it in code, but it is possible to check the principle in code. Here's a slightly modified version of that example that worked for me with no issues.
The bean
#DeclareRoles(value = {"Administrator"})
#Stateless
#WebService(
portName = "CalculatorPort",
serviceName = "CalculatorWsService",
targetNamespace = "http://superbiz.org/wsdl",
endpointInterface = "org.superbiz.calculator.CalculatorWs")
public class CalculatorImpl implements CalculatorWs, CalculatorRemote {
#Resource
private WebServiceContext webServiceContext;
#RolesAllowed(value = {"Administrator"})
public int sum(int add1, int add2) {
// maybe log the principal or something -- prints "jane" in the test
System.out.print(webServiceContext.getUserPrincipal());
return add1 + add2;
}
#RolesAllowed(value = {"Administrator"})
public int multiply(int mul1, int mul2) {
return mul1 * mul2;
}
}
The Test
public class CalculatorTest extends TestCase {
private InitialContext initialContext;
protected void setUp() throws Exception {
Properties properties = new Properties();
properties.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.client.LocalInitialContextFactory");
properties.setProperty("openejb.embedded.remotable", "true");
initialContext = new InitialContext(properties);
}
/**
* Create a webservice client using wsdl url
*
* #throws Exception
*/
public void testCalculatorViaWsInterface() throws Exception {
URL url = new URL("http://127.0.0.1:4204/CalculatorImpl?wsdl");
QName calcServiceQName = new QName("http://superbiz.org/wsdl", "CalculatorWsService");
Service calcService = Service.create(url, calcServiceQName);
assertNotNull(calcService);
CalculatorWs calc = calcService.getPort(CalculatorWs.class);
((BindingProvider) calc).getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "jane");
((BindingProvider) calc).getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "waterfall");
assertEquals(10, calc.sum(4, 6));
assertEquals(12, calc.multiply(3, 4));
}
}
Libraries
If using maven, switch your normal openejb-core dependency to openejb-cxf like so. This will add Apache CXF and the OpenEJB/CXF integration code to your classpath.
<dependency>
<groupId>org.apache.openejb</groupId>
<artifactId>openejb-cxf</artifactId>
<version>3.1.4</version>
<scope>test</scope>
</dependency>
If not using maven, simplest approach is to just add all the jars from the lib/ directory of the OpenEJB zip file.
David,In your answer in CalculatorTest you have used CalculatorWs.class, Is it same interface as it is used in webservice side implementation. Do we have to create web service client?
Also in David's example Instead of
QName calcServiceQName = new QName("http://superbiz.org/wsdl", "CalculatorWsService");
use
QName calcServiceQName = new QName("http://superbiz.org/wsdl", "CalculatorPort");