I am using spring 3 + spring security 3 + hibernate.
I have some problems with mapping classes. I don't know why, but some classes are mapped they can be used by Hibernate but at the same time some (which are used for Spring Security) are not!
forum-security.xml:
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd">
<http auto-config='true'>
<intercept-url pattern="/**" access="ROLE_USER" />
</http>
<authentication-manager>
<authentication-provider user-service-ref="userDetailsService"/>
</authentication-manager>
</beans:beans>
UserServiceImpl:
package forum.service;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import forum.domain.ForumUser;
#Service
public class UserServiceImpl implements UserService{
#Autowired private SessionFactory sessionFactory;
#Autowired private Assembler assembler;
public List<ForumUser> listAllUsers(){
return null;
}
public List<ForumUser> listUsersBySellingPont(){
return null;
}
#Transactional
public ForumUser getUserByUsername(String username){
Session session = sessionFactory.getCurrentSession();
List<ForumUser> users = session.createQuery("from ForumUser").list();
ForumUser result = null;
for(ForumUser user : users){
if(user.getUsername().equals(username))
result = user;
}
return result;
}
public void addUser(ForumUser user){
}
public void updateUser(ForumUser user){
}
public void deleteUser(Integer id){
}
}
Assembler:
package forum.service;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import forum.domain.ForumUser;
import forum.domain.UserDetailsImpl;
#Service("assembler")
public class Assembler {
#Transactional(readOnly = true)
UserDetailsImpl buildUserFromUserEntity(ForumUser userEntity) {
Integer id = userEntity.getId();
String username = userEntity.getUsername();
String password = userEntity.getPassword();
String email = userEntity.getEmail();
Date enabled = userEntity.getEnabled();
Date lastEntered = userEntity.getLastEntered();
Date registered = userEntity.getRegistered();
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
for (GrantedAuthority role : userEntity.getAuthorities()) {
authorities.add(role);
}
UserDetailsImpl user = new UserDetailsImpl();
user.setId(id);
user.setUsername(username);
user.setPassword(password);
user.setEmail(email);
user.setEnabled(enabled);
user.setAuthorities(authorities);
user.setLastEntered(lastEntered);
user.setRegistered(registered);
return user;
}
}
And now classes that are not mapped by hibernate (other classes are mapped):
package forum.domain;
import java.util.Date;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.FetchType;
import javax.persistence.CascadeType;
import org.springframework.security.core.GrantedAuthority;
#Entity
#Table(name="users")
public class ForumUser {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id")
private Integer id;
#Column(name="username")
private String username;
#Column(name="password")
private String password;
#Column(name="email")
private String email;
#Column(name="registered")
private Date registered;
#Column(name="lastEntered")
private Date lastEntered;
#Column(name="enabled")
private Date enabled;
#OneToMany(cascade=CascadeType.REFRESH,fetch=FetchType.LAZY,mappedBy="forumUser")
private List<GrantedAuthority> authorities;
public Date getEnabled(){
return enabled;
}
public void setEnabled(Date enabled){
this.enabled = enabled;
}
public Integer getId(){
return id;
}
public void setId(Integer id){
this.id = id;
}
public String getUsername(){
return username;
}
public void setUsername(String username){
this.username = username;
}
public String getPassword(){
return password;
}
public void setPassword(String password){
this.password = password;
}
public String getEmail(){
return email;
}
public void setEmail(String email){
this.email = email;
}
public Date getRegistered(){
return registered;
}
public void setRegistered(Date registered){
this.registered = registered;
}
public Date getLastEntered(){
return lastEntered;
}
public void setLastEntered(Date lastEntered){
this.lastEntered = lastEntered;
}
public List<GrantedAuthority> getAuthorities() {
return authorities;
}
public void setAuthorities(List<GrantedAuthority> authorities){
this.authorities = authorities;
}
}
And the second class:
package forum.domain;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.ManyToOne;
import javax.persistence.CascadeType;
import javax.persistence.JoinColumn;
import javax.persistence.Table;
import org.springframework.security.core.GrantedAuthority;
#Entity
#Table(name="authorities")
public class Authority implements GrantedAuthority{
#ManyToOne(cascade=CascadeType.REFRESH,fetch=FetchType.LAZY)
#JoinColumn(name="userId")
private ForumUser forumUser;
#Column(name="authority")
private String authority;
public String getAuthority() {
return authority;
}
public void setAuthority(String authority) {
this.authority = authority;
}
}
So when I am trying to retrieve an user by username from DB (UserServiceImpl.getUserByUsername() from ForumUser), it throws
org.hibernate.hql.ast.QuerySyntaxException: ForumUser is not mapped [from ForumUser]
And if I change thir HQL to another, for example "from Forum" (it is another class, that is working) it will throw another exception, doesn't really matter what exactly, but the fact is that it mappes another class and can retrieve it.
How can I solve this problem?
Oh, I have found a solution! It all was because of my own inattention. I have forgotten to add new classes to a list of annotated persistent classes in my conf.
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.
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.
Why my interceptor doesn't work?
MyLog.java
#Inherited
#InterceptorBinding
#Retention(RUNTIME)
#Target({METHOD, TYPE})
public #interface MyLog {
}
MyLogger.java
#Interceptor
#MyLog
#Priority(Interceptor.Priority.APPLICATION)
public class MyLogger {
#AroundInvoke
public Object log(InvocationContext context) throws Exception{
System.out.println("begin " + context.getMethod().getName());
Object obj = context.proceed();
System.out.println("end " + context.getMethod().getName());
return obj;
}
}
PerguntaController.java
import interceptor.MyLog;
import java.io.Serializable;
import java.util.List;
import javax.ejb.EJB;
import javax.ejb.EJBException;
import javax.inject.Named;
import javax.enterprise.context.SessionScoped;
#Named("PerguntaController")
#SessionScoped
public class PerguntaController implements Serializable {
#EJB
private PerguntaFacade ejbFacade;
#MyLog
public List<> getAll() {
return ejbFacade.getAll();
}
#MyLog
public void update(Pergunta pergunta) {
ejbFacade.update(pergunta);
}
}
PerguntaFacade.java
import interceptor.MyLog;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
#Stateless
public class PerguntaFacade {
#PersistenceContext(unitName = "WebApplicationPU")
private EntityManager em;
#MyLog
public List<Pergunta> getAll() {
return em.createQuery("SELECT p FROM Pergunta p", Pergunta.class).getResultList();
}
#MyLog
public void update(Pergunta pergunta) {
//do something
}
}
When use getAll and update (from PerguntaController) in jsf page doesn't fire the interceptor neither getAll and update on PerguntaFacade. What im doing wrong?
Solved.
On beans.xml with bean-discovery-mode="annotated" doesn't work.
Then change to bean-discovery-mode="all" and works fine.
I have an init function in my ManagedBean that is view scoped. But I can't seem to get it to run when the page loads.
Its a private field in this Class
.............
package mike.food;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.codehaus.jackson.map.JsonMappingException;
#JsonIgnoreProperties(ignoreUnknown = true)
#ManagedBean(name = "nutrition")
#ViewScoped
public class NutritionixResponse implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1016196967087965738L;
private String total_hits;
private String max_score;
private ArrayList<Hits> hits;
private ArrayList<Hits> droppedhits;
public NutritionixResponse() throws JsonParseException, JsonMappingException, IOException {
}
#PostConstruct
public void init() {
this.droppedhits = new ArrayList<Hits>();
}
public String getTotal_hits() {
return total_hits;
}
public void setTotal_hits(String total_hits) {
this.total_hits = total_hits;
}
public String getMax_score() {
return max_score;
}
public void setMax_score(String max_score) {
this.max_score = max_score;
}
public ArrayList<Hits> getHits() {
return hits;
}
public void setHits(ArrayList<Hits> hits) {
this.hits = hits;
}
public ArrayList<Hits> getDroppedhits() {
return droppedhits;
}
public void setDroppedhits(ArrayList<Hits> droppedhits) {
this.droppedhits = droppedhits;
}
}
The main class
#JsonIgnoreProperties(ignoreUnknown = true)
#Manaents Serializable {
gedBean(name = "FoodClient")
#ViewScoped
public class FoodClient implem
/**
* Need to test something
*/
private static final long serialVersionUID = 3874520453001209544L;
private NutritionixResponse nurition;
And the page
<p:outputPanel id="dropArea">
<p:dataTable id="droppedfoodtable" var="food"
value="#{FoodClient.nurition.droppedhits}"
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.