filenotfoundexception running jerseyTest - missing applicationContext.xml - java

I'm running a test on Hello World trying to follow the Jersey Framework in my spring java program.
I have extended JerseyTest, but I'm getting the error above. The example Jersey gives link doesn't seem to help.
public class SimpleTest extends JerseyTest {
#Override
protected Application configure() {
return new ResourceConfig(RestService.class);
}
#Test
public void test() {
final String hello = target("\service\hello").request().get(HelloModel.class);
assertEquals("Hello World!", hello);
}
}

With Jersey 2.26 the dependency has changed to jersey-spring4, but to flush out the answer a little bit more if you don't want to spin up the entire Spring context.
Create the object:
final ResourceConfig resourceConfig = new ResourceConfig(restResource);
In my case, I just needed an empty context:
final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.refresh();
resourceConfig.property("contextConfig", context);
That was able to allow the JerseyTest to run successfully.

This is going to happen if you have the jersey-spring3 dependency. The default behavior is to look for this applicationContext.xml file (which is your Spring context configuration).
If you want to configure Spring for the test, you can do a couple things.
You could manually create the ApplicationContext and pass it to Jersey
ApplicationContext context = ...
return new ResourceConfig(RestService.class)
.property("contextConfig", context)
If you are using xml configuration, then you would create a ClassPathXmlApplicationContext. If you're using Java config, then you would create an AnnotationConfigApplicationContext.
If you need servlet servlet container support, check out the example in this post

Related

Ensure spring bean loaded from non spring context

I have spring application alongside (jersey 2.6 classes and ) servlets .
I need to get Spring bean(s) from jersey/non spring context,
Similar question suggested to get context in a static wrapper of context
public static ApplicationContext getContext() {
return context;
}
How can I be sure the context is already loaded or not null?
If I can't, how should I wait/check until it spring context is loaded?
In case of calling from jersey context or calling bean from a simple HttpServlet code
EDIT
Jersey is working fine using jersey-spring3 dependency jar, so my question is only about Servlets out of Spring control
EDIT 2
The application is loading spring different than #entpnerd suggested article
It register a Servlet implementing a WebApplicationInitializer
public class MyWebAppInitializer implements WebApplicationInitializer {
But also have DispatcherServlet configured in web.xml
How can the DispatcherServlet loaded only after Spring loaded?
Because we add Autowiring capabilities on its init method:
WebApplicationContextUtils.getRequiredWebApplicationContext(config.getServletContext())
.getAutowireCapableBeanFactory().autowireBean(this);
Is adding a timeout before serving requests is the most prefer solution or is there a tweak in class loading that can take care of it?
EDIT 3
I found answers and answers of injecting, but not why Spring is loaded before Servlet.
The idea is quite simple, although the actual implementation may vary depending on an exact way of Spring boot and Jersery initialization.
An idea:
Spring boot, as being a purely runtime framework, is all about proper loading the application context (from the question standpoint).
So, bottom line, when it's loaded there is an application context somewhere in memory, and its possible to access beans from this application context.
Now, since you say that Jersey is not spring/spring-boot driven, this application context has to be reachable from some kind of static global variable by Jersey, it's quite ugly but should work.
So the idea has two steps:
Put an application context reference to some static holder accessible from Jersey.
Read this value in some infrastructure level code from Jersey component.
A Possible Implementation
Technically step one can be done by implementing some kind of spring boot listener that will store application context in some kind of singleton:
enum ApplicationContextHolder {
INSTANCE;
private ApplicationContext ctx;
void setApplicationContext(ApplicationContext ctx) {
this.ctx = ctx;
}
ApplicationContext getCtx() {
return this.ctx;
}
}
// and a listener (spring boot provides many ways to register one, but the
// implementation should be something like this):
// The main point is that its managed by spring boot, and hence and access to
// the application context
class StartupListener implements ApplicationListener<ContextRefreshedEvent> {
#Override
public void onApplicationEvent(ContextRefreshedEvent event) {
ApplicationContextHolder
.INSTANCE
.setApplicationContext(event.getApplicationContext());
}
}
Now the step 2 is:
class MyJerseyOrWhateverComponentThatWantsToAccessApplicationContext {
public void foo() {
ApplicationContext ctx = ApplicationContextHolder.INSTANCE.getCtx();
...
ctx.getBean(...);
}
}
So a viable solution for this could happen in two stages:
A Spring bean gets the ApplicationContext instance and sends it to a static singleton outside of the Spring context.
Your standalone servlet gets the ApplicationContext instance from the static singleton and verifies that the right beans have been loaded.
Consider the following code as an example:
SpringMetaBean.java
// #Component so that it's part of the Spring context
// Implement ApplicationContextAware so that the ApplicationContext will be loaded
// correctly
#Component
public class SpringMetaBean implements ApplicationContextAware {
private ApplicationContext appCtx;
public setApplicationContext(ApplicationContext appCtx) {
this.appCtx = appCtx;
}
// #PostConstruct so that when loaded into the Spring context, this method will
// automatically execute and notify ApplicationContextHolder with a reference to
// the ApplicationContext
#PostConstruct
public void setup() {
ApplicationContextHolder.set(this.appCtx);
}
}
ApplicationContextHolder.java
public class ApplicationContextHolder {
// ensure the reference is thread-safe because Spring and standalone Servlet will
// probably be running on different threads.
private final AtomicReference<ApplicationContext> appCtxContainer = new AtomicReference<>();
public void set(ApplicationContext appCtx) {
this.appCtxContainer.set(appCtx);
}
public ApplicationContext get() {
return this.appCtxContainer.get();
}
}
MyStandaloneServlet.java
public class MyStandaloneServlet {
// my request handler method
public void getResponse(HttpServletRequest rq) {
ApplicationContext springAppCtx = ApplicationContextHolder.get();
// if not null, we know that Spring has been loaded and we can dig into the
// application context.
}
}

does custom resourceloader work the same in spring boot 1.4.3

Hi I have been using a custom resource loader with spring boot like below for quite some time
public static void main(String[] args) {
LOG.info("Starting up....");
SpringApplicationBuilder builder = new SpringApplicationBuilder(Service.class);
SpringApplication app = builder.application();
// TODO see if ProtocolResolver can be used here
app.setResourceLoader(new EnhancedResourceLoader());
app.run(args);
}
and my custom resource is something like
#Aws
#Configuration
#PropertySource({ "s3://${cloud.aws.vpc-name}/creds/${cloud.aws.stack-name}/testprops.properties", })
public static class Config {
}
This used to work fine before I did the upgrade . Now seems the custom s3 url doesn't get captured in my custom resource loader . Have there been any changes or is there a different way now to do this .Please help
AS of now to fix as per https://twitter.com/ankinson/status/821401622001684481 I have removed the dependency for spring boot devtools and it works .Guess will test the same in the next 1.5.x release if that fixes it .

Functional tests with Jersey Test, Grizzly and HK2 Dependency Injection

I'm attempting to write functional tests for my REST API using the Jersey Test framework. However, I've seem to hit a roadblock when it comes to using dependency injection within my functional tests. My main application looks like this:
#ApplicationPath("/")
public class Application extends ResourceConfig {
private static final URI BASE_URI = URI.create("http://localhost:8080/api/");
public static void main(String[] args) throws Exception {
System.out.println("Starting application...");
final ServiceLocator locator = ServiceLocatorUtilities.createAndPopulateServiceLocator();
final ResourceConfig resourceConfig = new ResourceConfig();
resourceConfig.register(JacksonFeature.class);
resourceConfig.register(LoggingFeature.class);
resourceConfig.packages(true, "my.package.name");
final HttpServer server = GrizzlyHttpServerFactory.createHttpServer(BASE_URI, resourceConfig, locator);
Runtime.getRuntime().addShutdownHook(new Thread(server::shutdownNow));
server.start();
Thread.currentThread().join();
}
}
Notice here that I'm using the HK2's ServiceLocatorUtilities.createAndPopulateServiceLocator() method in order to read the hk2-metadata-generator file. This method creates a ServiceLocator object which then in turn is passed to the GrizzlyHttpServerFactory.createHttpServer method. This all works great for running the Grizzly server, however, the question I have now is how do I create functional tests for my application with the Jersey Test Framework?
My unit test currently looks like this:
public class FormsResourceTest extends JerseyTest {
#Override
protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
return new GrizzlyWebTestContainerFactory();
}
#Test
public void testMe() {
Response response = target("/test").request().get();
assertEquals("Should return status 200", 200, response.getStatus());
}
}
Is there even a way to use the HK2 service locator with the Jersey Test framework or do I need to treat my application as an external container and use the external container provider as documented here: External container?
Also, since these are functional tests, mocking the injected services is not an option here.
You can use the Locator Bridge to take two separate locator (the one you created and the one from Jersey) and bridge them together. The bridge can be made bi-directional as well (within limits) and so it'll appear in most normal usage to be one large ServiceLocator.
Note that there was a bug fixed this week with the ServiceLocator bridge which has not yet been pushed out to maven but will (probably) be pushed sometime next week. See HK2-295

spring boot request endpoints return 404 [duplicate]

The application uses JDK 8, Spring Boot & Spring Boot Jersey starter and is packaged as a WAR (although it is locally run via Spring Boot Maven plugin).
What I would like to do is to get the documentation I generate on the fly (at build time) as a welcome page.
I tried several approaches:
letting Jersey serving the static contents by configuring in application.properties the proper init parameter as described here
introduce a metadata-complete=false web.xml in order to list the generated HTML document as a welcome-file.
None of that worked out.
I would like to avoid having to enable Spring MVC or creating a Jersey resource just for serving a static file.
Any idea?
Here is the Jersey configuration class (I unsuccessfully tried to add a ServletProperties.FILTER_STATIC_CONTENT_REGEX there):
#ApplicationPath("/")
#ExposedApplication
#Component
public class ResourceConfiguration extends ResourceConfig {
public ResourceConfiguration() {
packages("xxx.api");
packages("xxx.config");
property(ServerProperties.BV_DISABLE_VALIDATE_ON_EXECUTABLE_OVERRIDE_CHECK, true);
property(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true);
}
}
And here is Spring Boot application class (I tried adding an application.properties with spring.jersey.init.jersey.config.servlet.filter.staticContentRegex=/.*html but it didn't work, I'm not exactly sure what the property key should be here):
#SpringBootApplication
#ComponentScan
#Import(DataConfiguration.class)
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Let me just first state, that the reason the static content won't be served is because of the default servlet mapping of the Jersey servlet, which is /*, and hogs up all the requests. So the default servlet that serves the static content can't be reached. Beside the below solution, the other solution is to simply change the servlet mapping. You can do that by either annotating your ResourceConfig subclass with #ApplicationPath("/another-mapping") or set the application.properties property spring.jersey.applicationPath.
In regards to your first approach, take a look at the Jersey ServletProperties. The property you are trying to configure is FILTER_STATIC_CONTENT_REGEX. It states:
The property is only applicable when Jersey servlet container is configured to run as a Filter, otherwise this property will be ignored
Spring Boot by default configures the Jersey servlet container as a Servlet (as mentioned here):
By default Jersey will be set up as a Servlet in a #Bean of type ServletRegistrationBean named jerseyServletRegistration. You can disable or override that bean by creating one of your own with the same name. You can also use a Filter instead of a Servlet by setting spring.jersey.type=filter (in which case the #Bean to replace or override is jerseyFilterRegistration).
So just set the property spring.jersey.type=filter in your application.properties, and it should work. I've tested this.
And FYI, whether configured as Servlet Filter or a Servlet, as far as Jersey is concerned, the functionality is the same.
As an aside, rather then using the FILTER_STATIC_CONTENT_REGEX, where you need to set up some complex regex to handle all static files, you can use the FILTER_FORWARD_ON_404. This is actually what I used to test. I just set it up in my ResourceConfig
#Component
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
packages("...");
property(ServletProperties.FILTER_FORWARD_ON_404, true);
}
}
For anyone who still can't get this to work, I followed the answer provided by #peeskillet, and had to make an additional change.
Previously I had created the following method in Application.java.
#Bean
public ServletRegistrationBean jerseyServlet() {
ServletRegistrationBean registration = new ServletRegistrationBean(new ServletContainer(), "/*");
registration.addInitParameter(ServletProperties.JAXRS_APPLICATION_CLASS, JerseyConfig.class.getName());
return registration;
}
The problem is that this registered the servlet for the /* path, and then setup the Jersey ResourceConfig configuration file.
Once I removed the above method, and placed the #Configuration annotation on my ResourceConfig class, I noticed the static resource could be retrieved via Spring Boot.
For completeness, this is a snippet of my ResourceConfig now.
#Configuration
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
// Application specific settings
property(ServletProperties.FILTER_FORWARD_ON_404, true);
}
}
This blog post was helpful in determining the difference approach for the ResourceConfig.
Below setup worked for me
Set
spring .jersey.type: filter
set FILTER_FORWARD_ON_404
#Configuration
public class MyResourceConfig extends ResourceConfig {
public MyResourceConfig () {
try {
register(XXX.class);
property(ServletProperties.FILTER_FORWARD_ON_404, true);
} catch (Exception e) {
LOGGER.error("Exception: ", e);
}
}
}
Note: Use #Configuration instead of #component

Java Spring 4 - why i need manually scan for beans in WebApplicationInitializer

I'm trying to setup a Web application with Spring 4.1 and Wicket 6.18. I want to use the full code approach. I have two test classes annotated with #Configuration and with #Bean. I want them to be discovered when i startup my app in Tomcat but it is not working unless i manually scan the base package in my custom WebApplicationInitialzer. By manually i mean to invoke AnnotationConfigWebApplicationContext.scan().
I looked through quite a few tutorials about the code based approach and didn't saw they do this. Even in the official spring docs they don't do this.
What i'm doing wrong that i need this and how to correct it?
My custom WebApplicationInitialzer looks like this:
public class WebAppInitializer implements WebApplicationInitializer {
private static final Logger logger = LoggerFactory.getLogger(WebAppInitializer.class);
#Override
public void onStartup(ServletContext container) throws ServletException {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
container.addListener(new ContextLoaderListener(context));
context.scan("pl.myhouse"); //why do i need this???
FilterRegistration filter = container.addFilter("wicket.myproject", WicketFilter.class);
filter.setInitParameter("applicationClassName", WicketApplication.class.getName());
filter.setInitParameter(WicketFilter.FILTER_MAPPING_PARAM, "/*");
filter.addMappingForUrlPatterns(null, false, "/*");
}
}
You both #The Head Rush and #Aeseir are correct. I was missing the rootContext.register(Appconfig.class) as well as the #ComponentScan. I even could share my knowledge further: Configuring Spring Wicket using Java Conf instead of xml :)

Categories

Resources