Test case for testing a jersey web resource using grizzle is giving me 404 - jersey-test-framework

I tried below way which is working fine
package test;
import static org.junit.Assert.assertEquals;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Application;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.DeploymentContext;
import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.ServletDeploymentContext;
import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory;
import org.glassfish.jersey.test.spi.TestContainerException;
import org.glassfish.jersey.test.spi.TestContainerFactory;
import org.junit.Test;
import com.mkyong.rest.HelloWorldService;
public class HelloWorldServiceTest extends JerseyTest{
#Path("hello")
public static class HelloResource {
#GET
public String getHello() {
return "Hello World!";
}
}
#Override
protected Application configure() {
return new ResourceConfig(HelloResource.class);
}
#Override
protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
return new GrizzlyWebTestContainerFactory();
}
#Override
protected DeploymentContext configureDeployment() {
return ServletDeploymentContext.forPackages(
getClass().getPackage().getName()).build();
}
#Test
public void testSingleNode() throws Exception {
final String hello = target("hello").request().get(String.class);
assertEquals("Hello World!", hello);
}
}
When i tried to replace the resource with resource which is outside of this test class and package like below
package test;
import static org.junit.Assert.assertEquals;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Application;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.DeploymentContext;
import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.ServletDeploymentContext;
import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory;
import org.glassfish.jersey.test.spi.TestContainerException;
import org.glassfish.jersey.test.spi.TestContainerFactory;
import org.junit.Test;
import com.mkyong.rest.HelloWorldService;
public class HelloWorldServiceTest extends JerseyTest{
#Path("hello")
public static class HelloResource {
#GET
public String getHello() {
return "Hello World!";
}
}
#Override
protected Application configure() {
return new ResourceConfig(HelloWorldService.class);
}
#Override
protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
return new GrizzlyWebTestContainerFactory();
}
#Override
protected DeploymentContext configureDeployment() {
return ServletDeploymentContext.forPackages(
getClass().getPackage().getName()).build();
}
#Test
public void testSingleNode() throws Exception {
final String hello = target("hello").path("Test").request().get(String.class);
assertEquals("Jersey say : Test", hello);
}
}
HelloWorldService.java
package com.mkyong.rest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
#Path("/hello")
public class HelloWorldService {
#GET
#Path("/{param}")
#Produces(MediaType.APPLICATION_JSON)
public Response getMsg(#PathParam("param") String msg) {
String output = "Jersey say : " + msg;
return Response.status(200).entity(output).build();
}
}
RestApplication.java
package rest;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;
import com.mkyong.rest.HelloWorldService;
public class RestApplication extends Application{
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> s = new HashSet<Class<?>>();
s.add(HelloWorldService.class);
return s;
}
}
web.xml
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Restful Web Application</display-name>
<servlet>
<servlet-name>rs-servlet</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>rest.RestApplication</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>rs-servlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
I got an exception
javax.ws.rs.NotFoundException: HTTP 404 Not Found
at org.glassfish.jersey.client.JerseyInvocation.convertToException(JerseyInvocation.java:917)
at org.glassfish.jersey.client.JerseyInvocation.translate(JerseyInvocation.java:770)
at org.glassfish.jersey.client.JerseyInvocation.access$500(JerseyInvocation.java:90)
at org.glassfish.jersey.client.JerseyInvocation$2.call(JerseyInvocation.java:671)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:228)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:423)
at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:667)
at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:396)
at org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:296)
at test.HelloWorldServiceTest.testSingleNode(HelloWorldServiceTest.java:48)
Can any one correct me where i went wrong...

Look at this
#Override
protected DeploymentContext configureDeployment() {
return ServletDeploymentContext.forPackages(
getClass().getPackage().getName()).build();
}
The forPackages is saying what package to scan for #Path and #Provider annotated classes, and automatically register them. The reason it works in the first example is that the resource class (the class annotated with #Path is in the getClass().getPackage().getName() package.
This method
#Override
protected Application configure() {
return new ResourceConfig(HelloWorldService.class);
}
is never called, because you override the getDeploymentContext(). Normally, if you don't override that method, it will call the configure method to register the application with the deployment context. But you neve do this.
So instead of the forPackages, you should use one of the ServletDeploymentContext.builder methods, that accept an Application class
return ServletDeploymentContext.builder(configure()).build()
return ServletDeploymentContext.builder(RestApplication.class).build();
OR
#Override
public ResourceConfig configure() {
return new ResourceConfig(HelloWorldService.class);
}
#Override
public ServletDeploymentContext configureDeployment() {
return SerlvetDeploymentContext.forServlet(new ServletContainer(configure));
}
One thing to note it that you only need to override the getTestContainerFactory and the configureDeployment if you wan to set up a servlet environment. Meaning, you need to use servlet APIs like HttpServletRequest, ServletContext, etc, in your application. If you don't need a servlet environment, just overriding configure is enough.

Related

Spring webflux - ServerWebExchangeDecorator code is not executed when an exception is thrown

I have a Webflux application, where I have a ServerWebExchangeDecorator that decorates the request and responses. I have overrides to do some logging and then call the super methods.
This is what I have in code:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.ServerWebExchangeDecorator;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
#Component
public class LoggingWebFilter implements WebFilter {
#Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
return chain.filter(decorate(exchange));
}
private ServerWebExchange decorate(ServerWebExchange exchange) {
final ServerHttpRequest decoratedRequest = new LoggingServerHttpRequestDecorator(exchange.getRequest());
final ServerHttpResponse decoratedResponse = new LoggingServerHttpResponseDecorator(exchange.getResponse());
return new ServerWebExchangeDecorator(exchange) {
#Override
public ServerHttpRequest getRequest() {
return decoratedRequest;
}
#Override
public ServerHttpResponse getResponse() {
return decoratedResponse;
}
};
}
}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import reactor.core.publisher.Flux;
public class LoggingServerHttpRequestDecorator extends ServerHttpRequestDecorator {
private static final Logger logger = LoggerFactory.getLogger(LoggingServerHttpRequestDecorator.class);
public LoggingServerHttpRequestDecorator(ServerHttpRequest delegate) {
super(delegate);
}
#Override
public Flux<DataBuffer> getBody() {
logger.info("getBody method");
return super.getBody();
}
}
import org.reactivestreams.Publisher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import reactor.core.publisher.Mono;
public class LoggingServerHttpResponseDecorator extends ServerHttpResponseDecorator {
private static final Logger logger = LoggerFactory.getLogger(LoggingServerHttpResponseDecorator.class);
public LoggingServerHttpResponseDecorator(ServerHttpResponse delegate) {
super(delegate);
}
#Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
logger.info("writeWith method");//THIS LINE IS NOT EXECUTED WHEN AN EXCEPTION IS THROWN
return super.writeWith(body);
}
#Override
public Mono<Void> writeAndFlushWith(Publisher<? extends Publisher<? extends DataBuffer>> body) {
logger.info("writeAndFlushWith method");
return super.writeAndFlushWith(body);
}
}
When I do a happy path with a POST request, this works fine, but when an exception is thrown, the Response Decorator is omitted and my custom code is not being executed.
This is a controller code to replicate the issue:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
#RestController
#RequestMapping("/decorator-demo")
public class DecoratorDemoController {
/** The Constant logger. */
private static final Logger logger = LoggerFactory.getLogger(DecoratorDemoController.class);
#PostMapping(produces = MediaType.APPLICATION_STREAM_JSON_VALUE, consumes = MediaType.APPLICATION_STREAM_JSON_VALUE)
public Mono<ResponseEntity<String>> postData(#RequestBody String id) {
logger.info("attempting to post the data");
if(id.length() == 1){
Mono<String> created = Mono.just(id);
return created.flatMap(vo -> Mono.just(ResponseEntity.status(HttpStatus.CREATED).body(vo)));
}
throw new IllegalArgumentException("String length must be 1");
}
}
When I post a single character, I have the logs I am expecting:
LoggingServerHttpRequestDecorator : getBody method
DecoratorDemoController : attempting to post the data
LoggingServerHttpResponseDecorator : writeWith method
But when I post more than one character, this is the logs I am having:
LoggingServerHttpRequestDecorator : getBody method
DecoratorDemoController : attempting to post the data
AbstractErrorWebExceptionHandler : [0b933716] 500 Server Error for HTTP POST "/decorator-demo"
Am I doing something wrong, or missing something?
Try this
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.reactivestreams.Publisher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.NettyWriteResponseFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
#Component
public class ResponseInterceptorFilter implements Ordered, GlobalFilter {
private static final Logger log = LoggerFactory.getLogger(ResponseInterceptorFilter.class);
public ResponseInterceptorFilter(SqsPublisher sqsPublisher) {
this.sqsPublisher = sqsPublisher;
}
#Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpResponse response = exchange.getResponse();
DataBufferFactory dataBufferFactory = response.bufferFactory();
ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(response) {
#Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
if (!(body instanceof Flux)) {
return super.writeWith(body);
}
Flux<? extends DataBuffer> flux = (Flux<? extends DataBuffer>) body;
return super.writeWith(flux.buffer().map(dataBuffers -> {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
dataBuffers.forEach(buffer -> {
// three byte copies here
byte[] array = new byte[buffer.readableByteCount()];
buffer.read(array);
try {
outputStream.write(array);
} catch (IOException e) {
// TODO: need catch?
}
DataBufferUtils.release(buffer);
});
byte[] write = outputStream.toByteArray();
String responseBody = new String(write);
log.debug("Response ----> {}", responseBody);
response.getHeaders().setContentLength(write.length);
return dataBufferFactory.wrap(write);
}));
}
};
ServerWebExchange serverWebExchange = exchange.mutate().response(decoratedResponse).build();
return chain.filter(serverWebExchange);
}
#Override
public int getOrder() {
return NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER - 1; // this is important
}
}

How to resolve view in thymleaf + Springboot?

Currently, i have function, which is to convert the data from MYSQL to CSV. The CSV function contain the webconfig where use the viewResolver. The problem is, when i used below function, the page cannot view but the CSV file can be download and vice versa. Is there anything that i need to configure ?
-Configure ContentNegotiatingViewResolver
#Bean
public ViewResolver contentNegotiatingViewResolver(ContentNegotiationManager manager) {
ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
resolver.setContentNegotiationManager(manager);
// Define all possible view resolvers
List<ViewResolver> resolvers = new ArrayList<>();
resolvers.add(csvViewResolver());
resolver.setViewResolvers(resolvers);
return resolver;
}
WebConfig- full code
package com.portal.dmtt.csvDownload.config;
import com.portal.dmtt.csvDownload.viewResolver.CsvViewResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.ContentNegotiatingViewResolver;
import java.util.ArrayList;
import java.util.List;
#Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer
.defaultContentType(MediaType.APPLICATION_JSON)
.favorPathExtension(true);
}
/*
* Configure ContentNegotiatingViewResolver
*/
#Bean
public ViewResolver contentNegotiatingViewResolver(ContentNegotiationManager manager) {
ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
resolver.setContentNegotiationManager(manager);
// Define all possible view resolvers
List<ViewResolver> resolvers = new ArrayList<>();
resolvers.add(csvViewResolver());
resolver.setViewResolvers(resolvers);
return resolver;
}
/*
* Configure View resolver to provide Csv output using Super Csv library to
* generate Csv output for an object content
*/
#Bean
public ViewResolver csvViewResolver() {
return new CsvViewResolver();
}
}
Export Controller
package com.portal.dmtt.csvDownload.controller;
import com.portal.dmtt.repo.dmttDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
#Controller
public class ExportController {
#Autowired
private dmttDAO dmttDAO;
/**
* Handle request to download an Excel document
*/
#GetMapping("/dl")
public String download(Model model) {
model.addAttribute("results", dmttDAO.getAllResultSet());
return "";
}
}
Abstract View
package com.portal.dmtt.csvDownload.view;
import org.springframework.web.servlet.view.AbstractView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
public abstract class AbstractCsvView extends AbstractView {
private static final String CONTENT_TYPE = "text/csv";
public AbstractCsvView() {
setContentType(CONTENT_TYPE);
}
#Override
protected boolean generatesDownloadContent() {
return true;
}
#Override
protected final void renderMergedOutputModel(
Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
response.setContentType(getContentType());
buildCsvDocument(model, request, response);
}
protected abstract void buildCsvDocument(
Map<String, Object> model, HttpServletRequest request, HttpServletResponse response)
throws Exception;
}
CSV View
package com.portal.dmtt.csvDownload.view;
import com.portal.dmtt.model.exceptionMonitoring.FN_Result_Set;
import org.supercsv.io.CsvBeanWriter;
import org.supercsv.io.ICsvBeanWriter;
import org.supercsv.prefs.CsvPreference;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
public class CsvView extends AbstractCsvView {
#Override
protected void buildCsvDocument(Map<String, Object> model, HttpServletRequest request, HttpServletResponse
response) throws Exception {
response.setHeader("Content-Disposition", "attachment; filename=\"my-csv-file.csv\"");
List<FN_Result_Set> fnResultSetList = (List<FN_Result_Set>) model.get("results");
String[] header = {"SP_ID", "SP_ID", "XFER_XMIT_STATUS", "XFER_FILE_NAME", "UPDATE_TS", "YYMM", "REMARKS"};
try {
ICsvBeanWriter csvWriter = new CsvBeanWriter(response.getWriter(),
CsvPreference.STANDARD_PREFERENCE);
csvWriter.writeHeader(header);
for (FN_Result_Set user : fnResultSetList) {
csvWriter.write(user, header);
}
csvWriter.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
View Resolver
package com.portal.dmtt.csvDownload.viewResolver;
import com.portal.dmtt.csvDownload.view.CsvView;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import java.util.Locale;
public class CsvViewResolver implements ViewResolver {
#Override
public View resolveViewName(String s, Locale locale) throws Exception {
return new CsvView();
}
}
One of the problems is that your CSVViewResolver is resolving a view for any view name. You may want to return null from CSVViewResolver.resolveViewName() if s, the view name, is not empty .
Another issue is that the browser (at least my Chrome) doesn't send text/csv as Accept header, but text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Set the media type explicitly in configureContentNegotiation for CSV:
#Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer
.defaultContentType(MediaType.APPLICATION_JSON)
.favorPathExtension(true)
.mediaType("csv", MediaType.parseMediaType("text/csv"));
}
Remove the Bean contentNegotiatingViewResolver
You shouldn't create a contentNegotiatingViewResolver as one is provided by Spring Boot. If you provide one, you will have two of this type, and yours will not have the Thymeleaf ViewResolver. As your CSVViewResolver will return a view for any view name, the view will be resolved in the ContentNegotiatingViewResolver provided by you, not in the one provided by Spring.
Details:
The csvViewResolver bean will be picked up by the Spring Boot's ContentNegotiatingViewResolver along others like BeanNameViewResolver, ThymeleafViewResolver, ViewResolverComposite, InternalResourceViewResolver.
To debug this set a breakpoint on DispatcherServlet.resolveViewName:
protected View resolveViewName(String viewName, Map<String, Object> model, Locale locale,
HttpServletRequest request) throws Exception {
for (ViewResolver viewResolver : this.viewResolvers) {
View view = viewResolver.resolveViewName(viewName, locale);
if (view != null) {
return view;
}
}
return null;
}

Spring MVC Java Config issues

I am trying to do an example to change the xml config to Java config for Spring MVC. But my simple example is not working. On running this project on server, I can't see any beans initializing or the dispatcher servlet name on console.
and I get 404 error on running the http://localhost:8080/Servlet3Example/
I have created a maven project and following is my code:
package com.project.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class MyDispatcherServlet extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
System.out.println("get root config");
//return new Class[]{RootConfig.class};
return null;
}
#Override
protected Class<?>[] getServletConfigClasses() {
System.out.println("get web config");
return new Class[]{WebConfig.class};
}
#Override
protected String[] getServletMappings() {
System.out.println("in dispatcher servlet");
return new String[] {"/"};
}
}
And the WebConfig is:
package com.project.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
#Configuration
#EnableWebMvc
#ComponentScan(basePackages={"com.project.controllers"})
public class WebConfig extends WebMvcConfigurerAdapter {
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setSuffix(".jsp");
viewResolver.setPrefix("/WEB-INF/views/");
return viewResolver;
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
And controller:
package com.project.controllers;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
#Controller
public class HomeController {
#RequestMapping(value="/",method=RequestMethod.GET)
public String home()
{
return "home";
}
}
Can you please change #ComponentScan to #ComponentScan(basePackages={"com.project.*"})

EJB persistence not working

I have a example EJB persistence with EJB module run on Jboss 5GA , JDK 6 . Default package have 3 file :
Book.java :
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="books")
public class Book implements Serializable{
private int id;
private String name;
public Book(){
}
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
#Column(name="id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
LibraryPersistentBean.java
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
#Stateless
public class LibraryPersistentBean implements LibraryPersistentBeanRemote {
#PersistenceContext(unitName="EJBModule1PU")
private EntityManager entityManager;
#Override
public void addBook(Book book) {
entityManager.persist(book);
}
#Override
public List<Book> getBooks() {
return entityManager.createQuery("From books").getResultList();
}
}
LibraryPersistentBeanRemote.java:
import java.util.List;
import javax.ejb.Remote;
#Remote
public interface LibraryPersistentBeanRemote {
void addBook(Book bookName);
List<Book> getBooks();
}
And configure files are persistence.xml and jboss-ds.xml that have lines of code :
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="EJBModule1PU" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/MysqlDS</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
</persistence>
<?xml version="1.0" encoding="UTF-8"?>
<datasources>
<local-tx-datasource>
<jndi-name>MysqlDS</jndi-name>
<connection-url>jdbc:mysql://localhost:3306/ejb_books?zeroDateTimeBehavior=convertToNull</connection-url>
<driver-class>com.mysql.jdbc.Driver</driver-class>
<user-name>root</user-name>
<password/>
<min-pool-size>5</min-pool-size>
<max-pool-size>20</max-pool-size>
<idle-timeout-minutes>5</idle-timeout-minutes>
</local-tx-datasource>
</datasources>
Client's application consist of :
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class JavaApplication1 {
public static void main(String[] args) throws NamingException {
try {
Book b = new Book();
b.setName("AI");
Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY,"org.jnp.interfaces.NamingContextFactory");
env.put(Context.URL_PKG_PREFIXES,"org.jboss.naming:org.jnp.interfaces");
env.put(Context.PROVIDER_URL, "jnp://localhost:1099");
Context ctx = new InitialContext(env);
LibraryPersistentBeanRemote libraryBean = (LibraryPersistentBeanRemote)ctx.lookup("LibraryPersistentBean/remote");
libraryBean.addBook(b);
} catch (NamingException ex) {
Logger.getLogger(JavaApplication1.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
and jboss-client.jar, EJB Module was imported
when run, errors were occured :
Mar 7, 2017 10:30:23 AM JavaApplication1 main
SEVERE: null
javax.naming.NoInitialContextException: Cannot instantiate class: org.jnp.interfaces.NamingContextFactory [Root exception is java.lang.ClassNotFoundException: org.jnp.interfaces.NamingContextFactory]
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:657)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288)
at javax.naming.InitialContext.init(InitialContext.java:223)
at javax.naming.InitialContext.<init>(InitialContext.java:197)
at JavaApplication1.main(JavaApplication1.java:25)
Caused by: java.lang.ClassNotFoundException: org.jnp.interfaces.NamingContextFactory
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:247)
at com.sun.naming.internal.VersionHelper12.loadClass(VersionHelper12.java:46)
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:654)
... 4 more
How to resolve these error ? thanks you so much !
"$JBOSS_HOME/jboss-as/client/jnp-client.jar" contains the missing class "org.jnp.interfaces.NamingContextFactory" , The "jnp-client.jar" is referred internally using the MANIFEST.MF file "class-path" entry of the "$JBOSS_HOME/client/jbossall-client.jar" file.
So the JBoss Client code users/developers need to make sure that in order to avoid the "[Caused by: java.lang.ClassNotFoundException: org.jnp.interfaces.NamingContextFactory]" exception users must include the "$JBOSS_HOME/client/jbossall-client.jar" in client's classpath.

WebApplicationContextUtils.getWebApplicationContext(ServletContext) returns NULL from ServletContextListener

I am unable to get WebApplicationContext inside ServletContextListener. I searched for solution but non of them are working for me. I would appreciate if any one can help. Thanks in advance.
Below are code snippets-
My AppConfig class:
package in.andonsystem.config;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = {"in.andonsystem"})
public class AppConfig extends WebMvcConfigurerAdapter{
#Bean
public ViewResolver viewResolver(){
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
#Bean
public MessageSource messageSource(){
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("messages");
return messageSource;
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("/static/");
}
}
My AppInitializer Class.
package in.andonsystem.config;
import javax.servlet.ServletRegistration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
public class Appinitializer implements WebApplicationInitializer{
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(AppConfig.class);
rootContext.setServletContext(servletContext);
// Manage the lifecycle of the root application context
servletContext.addListener(new ContextLoaderListener(rootContext));
rootContext.refresh();
// Register and map the dispatcher servlet
ServletRegistration.Dynamic dispatcher =
servletContext.addServlet("dispatcher", new DispatcherServlet(rootContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
My ContextListener Class:
package in.andonsystem.config;
import com.mysql.jdbc.AbandonedConnectionCleanupThread;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;
import java.util.logging.Logger;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
#WebListener
public class ContextListener implements ServletContextListener{
private Logger logger = Logger.getLogger("ContextListener");
#Override
public void contextInitialized(ServletContextEvent sce) {
logger.info("contextInitialized()");
WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());
System.out.println("Is rootContext null:" + (rootContext == null));
}
#Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
stdout output is always coming true.
What am I missing?
Finally came up with the solution. The problem was that ServletContextListener was being loaded before ContextLoaderListener and Therefore a WebApplicationContext returned was null because ContextLoaderListener must be loaded before ServletContextListener in order to get the rootContext.
I removed #WebListener annotation from my ContextListener and added this Listener Programatically in onStartup method of AppInitializer after Adding ContextLoaderListener.
Now my ContextListener without #WebListener annotation is:
public class ContextListener implements ServletContextListener{
private Logger logger = Logger.getLogger("ContextListener");
#Override
public void contextInitialized(ServletContextEvent sce) {
logger.info("contextInitialized()");
WebApplicationContext rootContext =
WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());
System.out.println("Is rootContext null:" + (rootContext == null));
}
#Override
public void contextDestroyed(ServletContextEvent sce) {
logger.info("contextDestroyed()");
}
}
and AppInitializer is :
public class Appinitializer implements WebApplicationInitializer{
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(AppConfig.class);
rootContext.setServletContext(servletContext);
// Manage the lifecycle of the root application context
servletContext.addListener(new ContextLoaderListener(rootContext));
//ContextListener must be added after ContextLoaderListener
servletContext.addListener(ContextListener.class);
// Register and map the dispatcher servlet
ServletRegistration.Dynamic dispatcher =
servletContext.addServlet("dispatcher", new DispatcherServlet(rootContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
Looks basically correct, but I think you should remove the following 2 lines from your initializer class:
rootContext.setServletContext(servletContext);
and
rootContext.refresh();

Resources