This is what I tried:
#RunWith(SpringRunner.class)
#DataJpaTest
#ActiveProfiles("h2")
#Rollback(false)
#AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
public class ServiceTest {
private EntityManager entityManager;
public ServiceTest(EntityManager entityManager) {
this.entityManager = entityManager;
}
#Test
public void findLocation() {
Location location = entityManager.find(Location.class, 2);
assertEquals(location.getName(), "Avenue");
}
#Test
public void updateLocation() {
Location location = entityManager.find(Location.class, 2);
location.setNo_people(10);
entityManager.persist(location);
entityManager.flush();
}
}
the error that I get is ' Runner org.junit.internal.runners.ErrorReportingRunner (used on class com.unibuc.AWBD_Project_v1.services.ServiceTest) does not support filtering and will therefore be run completely. Test class should have exactly one public zero-argument constructor'
Here is the LocationService:
#Service
public class LocationService implements BaseService<Location> {
private final LocationRepository locationRepository;
#Autowired
public LocationService(com.unibuc.AWBD_Project_v1.repositories.LocationRepository locationRepository) {
this.locationRepository = locationRepository;
}
#Override
public Location insert(Location object) {
return locationRepository.save(object);
}
#Override
public Location update(Long id, Location updatedObject) {
var foundId = locationRepository.findById(id);
return foundId.map(locationRepository::save).orElse(null);
}
#Override
public List<Location> getAll() {
return locationRepository.findAll();
}
#Override
public Optional<Location> getById(Long id) {
return locationRepository.findById(id);
}
#Override
public void deleteById(Long id)
{
try {
locationRepository.deleteById(id);
} catch (LocationException e) {
throw new LocationException("Location not found");
}
}
#Override
public Page<Location> findAll(int page, int size, String sortBy, String sortType){
Sort sort = sortType.equalsIgnoreCase(Sort.Direction.ASC.name()) ? Sort.by(sortBy).ascending() :
Sort.by(sortBy).descending();
Pageable pageable = PageRequest.of(page - 1, size, sort);
return locationRepository.findAll(pageable);
}
}
Hello there is 3 issues in your test code.
1 you should remove the EntityManager entityManager from your test constructor to have a runnable test class.
2 if you want to use entityManager inside your test class you should #Autowired it
public class ServiceTest {
#Autowired
private EntityManager entityManager;
3 It's look like you are testing entityManager and not your LocationService
In an unit test you should mock dependencies like entityManager using Mockito
It's seems like you wanted to create an integration test.
The 3 steps of one integration test of a service (exemple with findLocation())
Prepare the data inside a test database
Create a new location object and save it into database using the entityManager or the testEntityManager.
Execute your findLocation methode on the id
Don't forget to Autowire your service class.
Verify if the retrieved data is as expected
Compare the retrieved Location object with the one you've saved.
Here's the code
#RunWith(SpringRunner.class)
#DataJpaTest
#ActiveProfiles("h2")
#Rollback(false)
#AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
public class ServiceTest {
#Autowired
private EntityManager entityManager;
#Autowired
private LocationService locationService;
public ServiceTest() {
}
#Test
public void findLocation() {
//given
Location location = new Location(....);
entityManager.save(location);
//when
Location foundLocation=locationService.getById(location.getId());
//then
assertTrue(foundLocation.isPresent());
assertEquals(foundLocation.get().getName(), "Avenue");
}
If you have any question I'm available to help you.
Related
I had some trouble setting up unit test with my spring boot application. My main issue is with the "model" object that's needed in my controller, but I can't find a way to recreate it in my test, which is required to use my function.
here are the function I want to test
#Controller
public class AjoutAbscenceControler {
#Autowired
private AbsenceRepository absenceRepository;
#RequestMapping(value = { "/addAbsence" }, method = RequestMethod.GET)
public String showAddAbsencePage(Model model) {
Absence absence = new Absence();
model.addAttribute("Absence", absence);
return "addAbsence";
}
#RequestMapping(value = { "/addingAbsence" }, method = RequestMethod.POST)
public String saveAbsence(Model model, #ModelAttribute("absence") Absence absence) {
if (absence.getName() != null && absence.getName().length() > 0) {
absenceRepository.save(absence);
}
return "redirect:/userList";
}
}
I did try something like that
#RunWith(MockitoJUnitRunner.class)
public class AjoutAbscenceControlerTest {
#Mock
VacationRepository vacationRepository;
#Mock
CategoryRepository categoryRepository;
#InjectMocks
AjoutAbscenceControler controler;
public MockMvc mockMvc;
#Before
public void setUp() throws Exception{
mockMvc = MockMvcBuilders.standaloneSetup(controler).build();
}
#Test
public void showAddAbsencePagetest() {
AjoutAbscenceControler ajoutAbscenceControler =new AjoutAbscenceControler();
assertEquals("addAbsence",ajoutAbscenceControler.showAddAbsencePage(controler));
}
}
but I don't find any way to create a springfarmwork.ui.Model
If you're testing the logic of your controller you probably shouldn't create a Model object, but mock it, and verify the interactions against it:
#Mock
private Model model;
#Test
public void showAddAbsencePagetest() {
// Should probably be initialized in a #Before method,
// Initialized here for clarity only
AjoutAbscenceControler ajoutAbscenceControler = new AjoutAbscenceControler();
assertEquals("addAbsence", ajoutAbscenceControler.showAddAbsencePage(model));
Mockito.verify(model).addAttribute(eq("Absence"), any(Absence.class));
}
I have a controller
#RestController
public class Create {
#Autowired
private ComponentThatDoesSomething something;
#RequestMapping("/greeting")
public String call() {
something.updateCounter();
return "Hello World " + something.getCounter();
}
}
I have a component for that controller
#Component
public class ComponentThatDoesSomething {
private int counter = 0;
public void updateCounter () {
counter++;
}
public int getCounter() {
return counter;
}
}
I also have a test for my controller.
#RunWith(SpringRunner.class)
#SpringBootTest
public class ForumsApplicationTests {
#Test
public void contextLoads() {
Create subject = new Create();
subject.call();
subject.call();
assertEquals(subject.call(), "Hello World 2");
}
}
The test fails when the controller calls something.updateCounter(). I get a NullPointerException. While I understand it's possible to add #Autowired to a constructor I would like to know if there is anyway to do this with an #Autowired field. How do I make sure the #Autowired field annotation works in my test?
Spring doesn't auto wire your component cause you instantiate your Controller with new not with Spring, so Component is not instatntiated
The SpringMockMvc test check it correct:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest
public class CreateTest {
#Autowired
private WebApplicationContext context;
private MockMvc mvc;
#Before
public void setup() {
mvc = MockMvcBuilders
.webAppContextSetup(context)
.build();
}
#Test
public void testCall() throws Exception {
//increment first time
this.mvc.perform(get("/greeting"))
.andExpect(status().isOk());
//increment secont time and get response to check
String contentAsString = this.mvc.perform(get("/greeting"))
.andExpect(status().isOk()).andReturn()
.getResponse().getContentAsString();
assertEquals("Hello World 2", contentAsString);
}
}
The #Autowired class can be easily mocked and tested with MockitoJUnitRunner with the correct annotations.
With this you can do whatever you need to do with the mock object for the unit test.
Here is a quick example that will test the Create method call with mocked data from ComponentThatDoesSomething.
#RunWith(MockitoJUnitRunner.class)
public class CreateTest {
#InjectMocks
Create create;
#Mock
ComponentThatDoesSomething componentThatDoesSomething;
#Test
public void testCallWithCounterOf4() {
when(componentThatDoesSomething.getCounter()).thenReturn(4);
String result = create.call();
assertEquals("Hello World 4", result);
}
}
Use Mockito and inject a mock that you create. I would prefer constructor injection:
#RestController
public class Create {
private ComponentThatDoesSomething something;
#Autowired
public Create(ComponentThatDoesSomething c) {
this.something = c;
}
}
Don't use Spring in your Junit tests.
public CreateTest {
private Create create;
#Before
public void setUp() {
ComponentThatDoesSomething c = Mockito.mock(ComponentThatDoesSomething .class);
this.create = new Create(c);
}
}
We are building an application which uses Spring Boot. We write unit tests using TestNG and Mockito. However I find it pretty annoying to write when(...) configuration, I would like to use real components instead. I started to use #Spy components instead of mocks and this works pretty well until I need to put a Spy into a Spy. I'd like to avoid loading a Spring Context if possible, because creation of the context is very slow it looks like overkill for me to load it for at max 5 classes.
Is there any way, how could I use real code instead of Mocks and not loading whole Spring context? Or is my approach wrong at all and I should mock out all other classes then the tested one?
The other way to do this and may take some modifying of code on your end is to do it by constructor injection instead of field injection. Basically taking away any need of the spring context for testing. so the same from the other answer
Class to test
#Service
public class RecordServiceImpl implements RecordService
{
private final RecordRepository recordRepository;
#Autowired
public RecordServiceImpl(RecordRepository recordRepository)
{
this.recordRepository = recordRepository;
}
public Record find(String id)
{
return recordRepository.findOne(id);
}
public List<Record> findAll()
{
return recordRepository.findAll();
}
#Transactional
public Record save(Record record)
{
record.setRecordStatus("F");
return recordRepository.save(record);
}
}
Test Case
//#RunWith(SpringJUnit4ClassRunner.class)
//#ContextConfiguration(classes = {RecordServiceTestConfig.class})
public class RecordServiceTest
{
// #Autowired
private RecordRepository recordRepository = Mockito.mock(RecordRepository.class);
// #Autowired
private RecordService recordService;
#Before
public void setup()
{
Mockito.reset(recordRepository);
recordService = new RecordServiceImpl(recordRepository);
}
#Test
public void testFind()
{
Mockito.when(recordRepository.findOne(Mockito.anyString())).thenReturn(null);
Record record = recordService.find("1");
Assert.assertNull(record);
Mockito.verify(recordRepository, Mockito.times(1)).findOne(Mockito.eq("1"));
}
#Test
public void testSave()
{
Mockito.when(recordRepository.save(Mockito.any(Record.class)))
.thenAnswer(new Answer<Record>()
{
#Override
public Record answer(InvocationOnMock invocation) throws Throwable
{
Record record = (Record) invocation.getArguments()[0];
Assert.assertEquals("F", record.getRecordStatus());
return record;
}
});
Record record = new Record();
record = recordService.save(record);
Assert.assertNotNull(record);
Mockito.verify(recordRepository, Mockito.times(1)).save(Mockito.eq(record));
}
#Test
public void findAll()
{
Mockito.when(recordRepository.findAll()).thenReturn(new ArrayList<Record>());
List<Record> records = recordService.findAll();
Assert.assertNotNull(records);
Assert.assertEquals(0, records.size());
Mockito.verify(recordRepository, Mockito.times(1)).findAll();
}
}
I think your looking for like this with the use of #ContextConfiguration and #Configuration
Class to test
#Service
public class RecordServiceImpl implements RecordService
{
#Autowired
private RecordRepository recordRepository;
public Record find(String id)
{
return recordRepository.findOne(id);
}
public List<Record> findAll()
{
return recordRepository.findAll();
}
#Transactional
public Record save(Record record)
{
record.setRecordStatus("F");
return recordRepository.save(record);
}
}
Test Class
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {RecordServiceTestConfig.class})
public class RecordServiceTest
{
#Autowired
private RecordRepository recordRepository;
#Autowired
private RecordService recordService;
#Before
public void setup()
{
Mockito.reset(recordRepository);
}
#Test
public void testFind()
{
Mockito.when(recordRepository.findOne(Mockito.anyString())).thenReturn(null);
Record record = recordService.find("1");
Assert.assertNull(record);
Mockito.verify(recordRepository, Mockito.times(1)).findOne(Mockito.eq("1"));
}
#Test
public void testSave()
{
Mockito.when(recordRepository.save(Mockito.any(Record.class)))
.thenAnswer(new Answer<Record>()
{
#Override
public Record answer(InvocationOnMock invocation) throws Throwable
{
Record record = (Record) invocation.getArguments()[0];
Assert.assertEquals("F", record.getRecordStatus());
return record;
}
});
Record record = new Record();
record = recordService.save(record);
Assert.assertNotNull(record);
Mockito.verify(recordRepository, Mockito.times(1)).save(Mockito.eq(record));
}
#Test
public void findAll()
{
Mockito.when(recordRepository.findAll()).thenReturn(new ArrayList<Record>());
List<Record> records = recordService.findAll();
Assert.assertNotNull(records);
Assert.assertEquals(0, records.size());
Mockito.verify(recordRepository, Mockito.times(1)).findAll();
}
}
Test Class Configuration
#Configuration
public class RecordServiceTestConfig
{
#Bean
public RecordService recordService()
{
return new RecordServiceImpl();
}
#Bean
public RecordRepository recordRepository()
{
return Mockito.mock(RecordRepository.class);
}
}
the entire test class took 714ms to run the findAll test took 1ms.
If you are looking to configure your testcase using testng with Spring then you to mention
#ContextConfiguration(locations={
"/context.xml","/test-context.xml"})
at class level to load you spring file and extends your class org.springframework.test.context.testng.AbstractTestNGSpringContextTests
Sample
https://dzone.com/articles/spring-testing-support-testng
I am working with Spring MVC application.
I want to create new event:
fill data at page > controller handle this info > saving new event to DB
I have already created DAO layer and repository layer. But at some places, it behaves very strangely. I have created Java configuration for all repositories in the same way.
Here is Repositories Configuration snippet:
#Configuration
#ComponentScan({ "net.lelyak.edu.repository", "net.lelyak.edu.service" })
#Import({ DatabaseDAOConfiguration.class })
public class ApplicationConfiguration {
#Autowired
private UserDAO userDAO;
#Autowired
private EventDAO eventDAO;
#Autowired
private TicketDAO ticketDAO;
#Autowired
private AuditoriumDAO auditoriumDAO;
#Bean
public AuditoriumRepository auditoriumRepository() {
AuditoriumRepository auditoriumRepository = new AuditoriumRepository();
auditoriumRepository.setDao(auditoriumDAO);
return auditoriumRepository;
}
#Bean
public EventRepository eventRepository() {
EventRepository eventRepository = new EventRepository();
eventRepository.setDao(eventDAO);
return eventRepository;
}
I have faced strange behavior at the controller level.
Here is controller code snippet:
#Controller
#RequestMapping("events")
public class EventsController {
#Autowired
private AuditoriumRepository auditoriumRepository;
#Autowired
private EventRepository eventRepository;
#RequestMapping(path = "add", method = RequestMethod.POST)
public String addEvent(#RequestParam Map<String, String> allRequestParams) {
Event newEvent = new Event();
// get auditorium id from request
String auditoryIdString = allRequestParams.get("auditorium");
Long auditoryId = Long.parseLong(auditoryIdString);
Auditorium auditorium = auditoriumRepository.getById(auditoryId);
newEvent.setAuditorium(auditorium);
AuditoriumRepository is auto-wired fine.
Here is snippet from debug view:
but EventRepository isn't:
Configuration is the same for both. One repository is auto-wired fine, second fails. I am newly at Spring. I can't get a clue why does this happen?
Here is snippet of code from EventRepository:
public class EventRepository extends BaseRepository<Event, EventDAO> {
#Autowired
private AuditoriumRepository auditoriumRepository;
#Override
public int put(Event entity) {
auditoriumRepository.put(entity.getAuditorium());
return super.put(entity);
}
AuditoriumRepository code snippet:
public class AuditoriumRepository extends BaseRepository<Auditorium, AuditoriumDAO> {
#Override
public Auditorium preSave(Auditorium entity) {
return entity;
}
For saving new event to DB I have to use exactly EventRepository. It fails, of course, with following stack trace:
java.lang.NullPointerException
at net.lelyak.edu.repository.BaseRepository.put(BaseRepository.java:23)
at net.lelyak.edu.repository.EventRepository.put(EventRepository.java:20)
at net.lelyak.edu.repository.EventRepository$$FastClassBySpringCGLIB$$5de8d2a5.invoke()
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
I am using spring 4.2.4.RELEASE on Windows 10.
UPDATE:
BaseRepository code snippet:
public abstract class BaseRepository<T extends BaseEntity, E extends BaseDAO<T>> {
private E dao;
public E getDao() {
return dao;
}
public void setDao(E dao) {
this.dao = dao;
}
public int put(T entity) {
return dao.save(preSave(entity));
}
I can't understand why with the same configuration and repository structure. One instance is auto-wired by Spring fine, but the second one fails. How to find the root of this problem? And some solution.
UPDATE 2:
I have tried recommended solution, and added next setter to EventRepository:
public void setAuditoriumRepository(AuditoriumRepository auditoriumRepository) {
System.out.println("EventRepository.setAuditoriumRepository");
this.auditoriumRepository = auditoriumRepository;
}
As log message show this setter is executed. But keep failing for the same reason.
How to solve this issue?
i saw your code and the problem is not related to Spring and autowiring process. The problem is in your save method in BaseDAO class:
#Override
public Integer save(ENTITY entity) {
if (entity.getId() == null) {
insert(entity);
} else {
update(entity);
}
return null;
}
if you change the metod to return newly inserted/updated entity id it will work fine.
try to hardcode it just for test :
#Override
public Integer save(ENTITY entity) {
if (entity.getId() == null) {
insert(entity);
} else {
update(entity);
}
return 1;
}
and the problem is raised when you return null from save method then you are doing assignment in the EventsController class which is:
int eventId = eventRepository.put(newEvent); //this is null and throws NullPointerException because you are trying to assign null to primitive variable.
Try to inject the dependencies yourself in the Java #Configuration class. Update your EventRepository so that it has a setter method for the AuditoriumRepository dependency as follows
public class EventRepository extends BaseRepository<Event, EventDAO> {
private AuditoriumRepository auditoriumRepository;
#Override
public int put(Event entity) {
auditoriumRepository.put(entity.getAuditorium());
return super.put(entity);
}
public void setAuditoriumRepository(AuditoriumRepository auditoriumRepository){
this.auditoriumRepository=auditoriumRepository;
}
}
In your ApplicationConfiguration update as follow:
#Bean
public EventRepository eventRepository() {
EventRepository eventRepository = new EventRepository();
eventRepository.setDao(eventDAO);
eventRepository.setAuditoriumRepository(auditoriumRepository());
return eventRepository;
}
The null pointer exception is because auditoriumRepository is not set in the eventRepository bean.
So while creating the EventRepository bean in ApplicationConfiguration.java, we need to set auditoriumRepository as well.
For this I have updated ApplicationConfiguration as below:
public EventRepository eventRepository() {
EventRepository eventRepository = new EventRepository();
eventRepository.setDao(eventDAO);
eventRepository.setAuditoriumRepository(auditoriumRepository());
return eventRepository;
}
and added setter for auditoriumRepository in the EventRepository class
public AuditoriumRepository getAuditoriumRepository() {
return auditoriumRepository;
}
public void setAuditoriumRepository(AuditoriumRepository auditoriumRepository) {
this.auditoriumRepository = auditoriumRepository;
}
This will ensure that the NPE you are seeing will be resolved.
But subsequently we will still get the NPE at a different point now and i.e., at BaseDAO class. The save method is returning a null object and that is causing this NPE.
To resolve this, I have updated the save method of BaseDAO to return a dummy value of 1. You may want to return an appropriate value as per you application needs.
public Integer save(ENTITY entity) {
if (entity.getId() == null) {
insert(entity);
} else {
update(entity);
}
return 1;
}
With these changes, we will able to save the event and proceed to the next screen.
I have a little problem. I think this is typical question. However, I can't find good example. My application is using Jersey. And I want to test controller by client as test. Controller has private field - StudentService. When I debug test I see, that field is null. This leads to error. And I need to inject this field. I tried this:
My Controller
#Path("/student")
#Component
public class StudentResourse {
#Autowired
private StrudentService service; // this field Spring does not set
#Path("/getStudent/{id}")
#GET
#Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public Student getStudent(#PathParam("id") long id) {
return service.get(id);
}
}
My JUnit test class:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = "classpath:config.xml")
#TestExecutionListeners({ DbUnitTestExecutionListener.class,
DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class,
TransactionalTestExecutionListener.class })
public class StudentResourseTest extends JerseyTest {
private static final String PACKAGE_NAME = "com.example.servlet";
private static final String FILE_DATASET = "/data.xml";
#Autowired
private StudentService service; // this field is setted by Spring, but I do not need this field for test
public StudentResourseTest() {
super(new WebAppDescriptor.Builder(PACKAGE_NAME).build());
}
#Override
protected TestContainerFactory getTestContainerFactory() {
return new HTTPContainerFactory();
}
#Override
protected AppDescriptor configure() {
return new WebAppDescriptor.Builder("restful.server.resource")
.contextParam("contextConfigLocation",
"classpath:/config.xml").contextPath("/")
.servletClass(SpringServlet.class)
.contextListenerClass(ContextLoaderListener.class)
.requestListenerClass(RequestContextListener.class).build();
}
#Test
#DatabaseSetup(FILE_DATASET)
public void test() throws UnsupportedEncodingException {
ClientResponse response = resource().path("student").path("getStudent")
.path("100500").accept(MediaType.APPLICATION_XML)
.get(ClientResponse.class);
Student student = (Student) response.getEntity(Student.class);
} }
I guees, that problem is in test class. Because, when I run my application not in test, I can directly request students and everything working fine. But when I test classes, internal field of Controller does not setted. How to fix this bug? Thanks for your answers.
This is in my config.xml
<context:component-scan base-package="com.example" />
<bean id="StudentResourse" class="com.example.servlet.StudentResourse">
<property name="service" ref="studentService" />
</bean>
<bean id="service" class="com.example.service.StudentServiceImpl" />
One issue may be that you're trying to configure your test application in constructor and in configure() method. Use one or another but not both because in this case your configure() method is not invoked and hence you may not be using SpringServlet and everything that is defined in this method.
Reference: https://github.com/jiunjiunma/spring-jersey-test and http://geek.riffpie.com/unit-testing-restful-jersey-services-glued-together-with-spring/
Idea is to get a hold of the application context inside jersey by using ApplicationContextAware interface. There after we can grab the exact bean already created by spring, in your case, StudentService. Below example shows a mocked version of the dependency, SampleService, used to test the resource layer apis.
Resource class delegating the processing to a service layer
#Component
#Path("/sample")
public class SampleResource {
#Autowired
private SampleService sampleService;
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path ("/{id}")
public Sample getSample(#PathParam("id") int id) {
Sample sample = sampleService.getSample(id);
if (sample == null) {
throw new WebApplicationException(Response.Status.NOT_FOUND);
}
return sample;
}
}
Service layer encapsulating business logic
#Service
public class SampleService {
private static final Map<Integer, Sample> samples = new HashMap<>();
static {
samples.put(1, new Sample(1, "sample1"));
samples.put(2, new Sample(2, "sample2"));
}
public Sample getSample(int id) {
return samples.get(id);
}
}
Unit test for the above resource
public class SampleResourceTest extends SpringContextAwareJerseyTest {
private SampleService mockSampleService;
// create mock object for our test
#Bean
static public SampleService sampleService() {
return Mockito.mock(SampleService.class);
}
/**
* Create our own resource here so only the test resource is loaded. If
* we use #ComponentScan, the whole package will be scanned and more
* resources may be loaded (which is usually NOT what we want in a test).
*/
#Bean
static public SampleResource sampleResource() {
return new SampleResource();
}
// get the mock objects from the internal servlet context, because
// the app context may get recreated for each test so we have to set
// it before each run
#Before
public void setupMocks() {
mockSampleService = getContext().getBean(SampleService.class);
}
#Test
public void testMock() {
Assert.assertNotNull(mockSampleService);
}
#Test
public void testGetSample() {
// see how the mock object hijack the sample service, now id 3 is valid
Sample sample3 = new Sample(3, "sample3");
Mockito.when(mockSampleService.getSample(3)).thenReturn(sample3);
expect().statusCode(200).get(SERVLET_PATH + "/sample/3");
String jsonStr = get(SERVLET_PATH + "/sample/3").asString();
Assert.assertNotNull(jsonStr);
}
}
SpringContextAwareJerseyTest
#Configuration
public class SpringContextAwareJerseyTest extends JerseyTest {
protected static String SERVLET_PATH = "/api";
final private static ThreadLocal<ApplicationContext> context =
new ThreadLocal<>();
protected String getResourceLocation() {
return "example.rest";
}
protected String getContextConfigLocation() {
return getClass().getName();
}
static private String getContextHolderConfigLocation() {
return SpringContextAwareJerseyTest.class.getName();
}
protected WebAppDescriptor configure() {
String contextConfigLocation = getContextConfigLocation() + " " +
getContextHolderConfigLocation();
Map<String, String> initParams = new HashMap<>();
initParams.put("com.sun.jersey.config.property.packages",
getResourceLocation());
initParams.put("com.sun.jersey.api.json.POJOMappingFeature", "true");
return new WebAppDescriptor.Builder(initParams)
.servletClass(SpringServlet.class)
.contextParam(
"contextClass",
"org.springframework.web.context.support.AnnotationConfigWebApplicationContext")
.contextParam("contextConfigLocation", contextConfigLocation)
.servletPath(SERVLET_PATH) // if not specified, it set to root resource
.contextListenerClass(ContextLoaderListener.class)
.requestListenerClass(RequestContextListener.class)
.build();
}
protected final ApplicationContext getContext() {
return context.get();
}
#Bean
public static ContextHolder contextHolder() {
return new ContextHolder();
}
private static class ContextHolder implements ApplicationContextAware {
#Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
context.set(applicationContext);
}
}
}
Using the above with jersey 1.8