For some reason CDI seems unable to inject a string into a WebSocket ServerEndpoint. I am receiving the error Unsatisfied dependencies for type String with qualifiers #HelloMessage. I've included the Producer and ServerEndpoint implementations below. Any ideas? Injection seems to work if I create a custom class (say Messenger) and produce that instead of String.
Qualifier Implementation
import javax.inject.Qualifier;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
#Qualifier
#Retention(RUNTIME)
#Target({TYPE, METHOD, FIELD, PARAMETER})
public
#interface HelloMessage
{
}
Producer Implementation
import java.io.Serializable;
import javax.inject.Named;
import javax.ws.rs.Produces;
public
class StringProducer
implements Serializable
{
#Produces
#HelloMessage
public
String getMessage()
{
return "Hello, from Message!";
}
}
ServerEndpoint Implementation
import javax.inject.Inject;
import javax.inject.Named;
import javax.websocket.OnMessage;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
#ServerEndpoint(value = "/test")
public
class TestEndpoint
{
#OnMessage
public
void onMessage(Session session, String unused)
{
System.out.println(this.message);
}
#Inject #HelloMessage
private String message;
}
I needed to import javax.enterprise.inject.Produces instead of javax.ws.rs.Produces when defining the Producer.
Producer Implementation
import java.io.Serializable;
import javax.inject.Named;
import javax.enterprise.inject.Produces;
public
class StringProducer
implements Serializable
{
#Produces
#HelloMessage
public
String getMessage()
{
return "Hello, from Message!";
}
}
Related
I struggle with mocking a Panache repository.
Here is the Entity:
import javax.persistence.*;
#Entity
public class Thing {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
Simple repository:
import io.quarkus.hibernate.orm.panache.PanacheRepository;
import javax.enterprise.context.ApplicationScoped;
#ApplicationScoped
public class ThingRepository implements PanacheRepository<Thing> {
}
This is the resource:
import javax.inject.Inject;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.util.List;
#Path("/things")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public class ThingResource {
#Inject
ThingRepository thingRepository;
#GET
public List<Thing> list() {
return thingRepository.listAll();
}
}
and a simple test where I try to mock the repository:
import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.junit.mockito.InjectMock;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import javax.inject.Inject;
import java.util.ArrayList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertNotNull;
#QuarkusTest
class ThingResourceTest {
private Thing thing;
#Inject ThingResource thingResource;
#InjectMock ThingRepository thingRepository;
#BeforeEach
void setUp() {
Thing thing = new Thing();
thing.setId(1L);
}
#Test
void getAll() {
List<Thing> things = new ArrayList<Thing>();
things.add(thing);
Mockito.when(thingRepository.listAll()).thenReturn(things);
List<Thing> response = thingResource.list();
assertNotNull(response);
assertNotNull(response.get(0));
}
}
The test fails because the response list is <null>.
The debugger tells me the thingRepository is actually mocked. But for some reason Mockito.when().thenReturns() does not return the list I set up.
What am I missing?
Thank you for any help.
I had the thing double declared. One time as class variable, and again in setUp(). Bummer. I apologize for the noise.
Class under test:
import java.time.Duration;
import java.time.Instant;
import java.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
public class ServiceProcessorImpl implements ServiceProcessor {
#Autowired
private WebClient webClient;
#Override
public Mono<ServiceResponse> fetchOffersByItemIdAndStoreId(Mono<List<PriceAndOfferRequest>> list) {
String url = "<some url>";
Mono<ServiceResponse> response = webClient
.post()
.uri(url)
.headers(httpHeaders -> getHeaders(httpHeaders))
.body(list,List.class)
.retrieve()
.onStatus(HttpStatus::isError, clientResponse -> {
log.error("Error on API Calling : {}", clientResponse.statusCode());
return Mono.empty();
})
.bodyToMono(PnOServiceResponse.class);
return response;
}
}
Test Case:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
#RunWith(SpringRunner.class)
public class ServiceProcessorImplTest {
#Mock
private static WebClient webClientMock;
#Mock
private WebClient.RequestHeadersSpec requestHeadersSpecMock;
#Mock
private WebClient.RequestHeadersUriSpec requestHeadersUriSpecMock;
#Mock
private WebClient.RequestBodySpec requestBodySpecMock;
#Mock
private WebClient.RequestBodyUriSpec requestBodyUriSpecMock;
#Mock
private WebClient.ResponseSpec responseSpecMock;
#InjectMocks
static ServiceProcessorImpl pnOServiceProcessor;
#Test
public void test_whenErrorFromService_thenMonoEmpty() {
Mockito.when(webClientMock.post()).thenReturn(requestBodyUriSpecMock);
Mockito.when(requestBodyUriSpecMock.uri(Mockito.anyString())).thenReturn(requestBodySpecMock);
Mockito.when(requestBodySpecMock.headers(Mockito.any())).thenReturn(requestBodySpecMock);
Mockito.when(requestBodySpecMock.body(Mockito.any(Mono.class), Mockito.any(Class.class))).thenReturn(requestHeadersSpecMock);
Mockito.when(requestHeadersSpecMock.retrieve()).thenReturn(responseSpecMock);
Mockito.when(responseSpecMock.onStatus(Mockito.any(), Mockito.any())).thenReturn(responseSpecMock);
Mockito.when(responseSpecMock.bodyToMono(Mockito.eq(PnOServiceResponse.class))).thenReturn(Mono.empty());
Mono<List<PriceAndOfferRequest>> reqList = createPriceAndOfferRequestList();
Mono<PnOServiceResponse> pnOServiceResponseMono = pnOServiceProcessor.fetchOffersByItemIdAndStoreId(reqList);
StepVerifier.create(pnOServiceResponseMono)
.expectNextCount(0)
.verifyComplete();
}
private Mono<List<PriceAndOfferRequest>> createPriceAndOfferRequestList() {
PriceAndOfferRequest pnoRequest = new PriceAndOfferRequest();
pnoRequest.setItemId("12345");
pnoRequest.setStoreNumber("store12345");
List<PriceAndOfferRequest> list = Arrays.asList(pnoRequest);
return Mono.just(list);
}
private Mono<PnOServiceResponse> createMockPnOResponse() {
PnOServiceResponse pnOServiceResponse = new PnOServiceResponse();
OfferPriceDTO offerPriceDTO = new OfferPriceDTO();
PnOItem item = new PnOItem();
item.setItemId("12345");
offerPriceDTO.setItems(Arrays.asList(item));
pnOServiceResponse.setOfferPriceDTO(offerPriceDTO);
return Mono.just(pnOServiceResponse);
}
}
The code gives NullPointerException while calling .body() on the webClient in fetchOffersByItemIdAndStoreId method. Looks like there is some issue with the ArgumentMatcher in the test case when mocking the call to body() in Mockito.when(requestBodySpecMock.body(Mockito.any(Mono.class), Mockito.any(Class.class))).thenReturn(requestHeadersSpecMock);
Resolved.
Mockito.any(Object.class) worked me.
Mockito.when(requestBodySpecMock.body(Mockito.any(Object.class), Mockito.any(Class.class))).thenReturn(requestHeadersSpecMock);
You can use the generic matcher ArgumentMatchers.any()
i don't know exactly how to write tests for these following Classes especially for the Controller and Model. Is it to possible to test with jUnit ?
I heard from Selenium but first i would test with jUnit. Thanks for ur help and best regards.
Controller.class:
import factory.InfoMessageFactory;
import entity.Product;
import java.io.Serializable;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.inject.Named;
import model.ProductModel;
import project.Konstanten;
#Named(value = "ProductController")
#SessionScoped
public class ProductController implements Serializable {
private Product product;
#Inject
private ProductModel model;
#PostConstruct
public void init() {
this.product = new Product();
}
public String addProduct() {
this.model.newProduct(this.product);
}
public Product getProduct() {
return product;
}
public void setProdukt(Product product) {
this.product = product;
}
public List<Product> getProducts() {
return this.model.getProducts();
}
}
Model.class
package model;
import ejb.DB;
import entity.Product;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.enterprise.context.Dependent;
import javax.inject.Inject;
#Dependent
public class ProductModel implements Serializable{
#Inject
private DB db;
public boolean addProduct(Product p){
try{
db.persist(p);
}catch(Exception e){
System.out.println("Blablabla");
return false;
}
return true;
}
}
And DB.class
#Stateless
public class DB {
#Inject
#RealClass
private EntityManager em;
public void persist(Object object) {
em.persist(object);
}
In the ProductController, there is really not much to test.. unless there is more logic that you did not post.
For testing the ProductModel, or any service-like class having the DB dependency i would suggest adding a project dependency to one of the mocking frameworks (i suggest Mockito as it is the most mature of them all).
For the addProducts method you could end up with following tests:
import static org.mockito.Mockito.*;
import org.junit.Test;
import org.mockito.MockitoAnnotations;
public class ProductModelTest{
#Mock
private DB dbMock;
#InjectMocks
private ProdcutModel = new ProductModel();
#Before
public void init(){
MockitoAnnotations.iniMocks(this);
}
#Test
public void shouldReturnTrue_whenEntityPersisted(){
doNothing().when(dbMock).persist(any(Product.class));
boolean result = productModel.addProduct(new Product());
assertTrue(result);
}
#Test
public void shouldReturnFalse_whenEntityPersisted(){
doThrow(RuntimeException.class).when(dbMock).persist(any(Product.class));
boolean result = productModel.addProduct(new Product());
assertFalse(result);
}
}
Regarding the DB-like repository classes.. i normally do not unit-test them. IF so i run integration tests on them.
this code produces NullPointerException. I don't know why. When I put the code from constructor to some other void with #PostConstruct - it works. I tried to initiate klientFacade - but it's not working, either. The class KlientFacade is #Stateless.
package view;
import entity.Klient;
import facade.KlientFacade;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import static util.Messages.addFlashMessage;
#ManagedBean
#ViewScoped
public class ManageClient implements Serializable {
#EJB
private KlientFacade klientFacade;
private List<Klient> clientList;
public List<Klient> returnClientList(){
return getKlientFacade().findAll();
}
public ManageClient() {
clientList = new ArrayList<>();
clientList = returnClientList();
}
public String removeClient(Klient klient){
addFlashMessage("Klient ["+klient.getLogin()+"] został usunięty.");
getKlientFacade().remove(klient);
return "manage";
}
public List<Klient> getClientList() {
return clientList;
}
public void setClientList(List<Klient> clientList) {
this.clientList = clientList;
}
public KlientFacade getKlientFacade() {
return klientFacade;
}
public void setKlientFacade(KlientFacade klientFacade) {
this.klientFacade = klientFacade;
}
}
Well its because injected objects are not instantiated before the constructor call. Thats why you are not getting NPE with #PostConstruct annotation. If you still need to access injected fields in constructor, try http://openejb.apache.org/constructor-injection.html.
my sessionfacade class
package com.entity;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
#Stateless
public class UsersFacade extends AbstractFacade<Users> implements UsersFacadeLocal
{
#PersistenceContext(unitName = "My_communityPU")
private EntityManager em;
#Override
protected EntityManager getEntityManager() {
return em;
}
public UsersFacade() {
super(Users.class);
}
}
my managed bean class
package com.jsf;
import com.entity.Users;
import com.entity.UsersFacadeLocal;
import javax.inject.Named;
import javax.enterprise.context.SessionScoped;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import javax.annotation.ManagedBean;
import javax.ejb.EJB;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
#Named(value = "loginMB")
#ManagedBean
#SessionScoped
public class LoginMB implements Serializable {
#EJB
private UsersFacadeLocal usersFacade;
protected Users user;
protected List<Users> lusers;
protected String username;
protected String password;
public LoginMB() {
lusers=usersFacade.findAll();
}
}
I dont know why my ejb injection in to mangedbean is not working. I am getting null pointer exception when i am calling findall(); method by using usersFacade
I am working on netbeans ide with glassfish server. i am just learning jpa in jsf please let me know where i am doing wrong
Container injects the EJB only after instantiating the managed bean. Use #PostConstruct annotation and use the EJB there. The annotated method will be called after the injection.