i working with Spring mvc, using hibernate and JPA configuration,relation many-to-many, i'm using view technologies(jsp) test method in DAO(with controller,service) ok, when i move to writing test for DAO class , it fail, i don't know, Where am I wrong?, please could you tell me ? thanks you !
Student.java
#Entity
#Table(name = "Student")
public class Student {
#Id
#Column(name = "studentNumber", nullable = false)
private Integer studentNumber;
#Column(name = "studentName", nullable = false)
private String studentName;
#Column(name = "birthDay", nullable = false)
private String birthDay;
#Column(name = "birthPlace", nullable = false)
private String birthPlace;
#Column(name = "admissionDay", nullable = false)
private String admissionDay;
#Column(name = "score", nullable = false)
private Float score;
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE, mappedBy = "studentNumbers")
private Set<ClassRoom> classRooms = new HashSet<ClassRoom>();
ClassRoom.java
#Entity
#Table(name = "ClassRoom")
public class ClassRoom {
#Id
#Column(name = "classRoomID", unique = true, nullable = false)
private String classRoomID;
#Column(name = "classRoomName", nullable = false)
private String classRoomName;
#Column(name = "teacherName", nullable = false)
private String teacherName;
#JoinTable(name = "ClassRoom_Student", joinColumns = #JoinColumn(name = "classRoomID", referencedColumnName = "classRoomID", nullable = false, updatable = false) , inverseJoinColumns = #JoinColumn(name = "studentNumber", referencedColumnName = "studentNumber", nullable = false, updatable = false) )
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private Set<Student> studentNumbers = new HashSet<Student>();
DAO class
#Repository
public class StudentDAOImpl implements StudentDAO {
#PersistenceContext(unitName = "default")
private EntityManager entityManager;
#Override
public boolean insert(Student student) {
entityManager.persist(student);
return true;
}
#Override
public boolean update(Student student) {
entityManager.merge(student);
return true;
}
#Override
public boolean delete(Integer studentNumber) {
Student student = entityManager.find(Student.class, studentNumber);
entityManager.remove(student);
return true;
}
#Override
public Student getStudentByStudentNumber(Integer studentNumber) {
Student student = entityManager.find(Student.class, studentNumber);
return student;
}
#Override
public List<Student> getAllStudent() {
return entityManager.createQuery("FROM Student").getResultList();
}
#Override
public List<String> getClassOfStudent(Integer studentNumber) {
return entityManager
.createQuery("SELECT cs.classRoomID FROM Class_Student cs WHERE cs.studentNumber=" + studentNumber)
.getResultList();
}
#Override
public boolean deleteStudentClassStudent(Integer studentNumber) {
Query query = entityManager
.createQuery("DELETE FROM ClassRoom_Student cs WHERE cs.studentNumber = " + studentNumber);
query.executeUpdate();
return true;
}}
and mockTest
#ContextConfiguration(locations = { "classpath*:applicationContext.xml" })
#RunWith(SpringJUnit4ClassRunner.class)
public class Mockito {
#Mock
private static Student studentMock;
#Mock
private static ClassRoom classMock;
#Autowired
private StudentDAO studentDAO;
#Autowired
private ClassRoomDAO classRoomDAO;
#Test
public void testCreateObject() {
assertNotNull(studentDAO);
assertNotNull(classRoomDAO);
}
#Test
public void insertTest() {
Student student = new Student(111006, "ABC", "ABC", "ABC", "ABC", 10f);
studentDAO.insert(student);
List<Student> listStudent = studentDAO.getAllStudent();
when(studentDAO.insert(student)).thenReturn(true);
assertTrue(0 == listStudent.size());
}
#Test
public void testgetStudentByStudentNumber() {
Student student = new Student();
when(studentDAO.getStudentByStudentNumber(111000002)).thenReturn(student);
assertTrue(student != null);
}
#Test
public void updateTest() {
Student student = studentDAO.getStudentByStudentNumber(111002);
student.setStudentName("new name");
student.setAdmissionDay("new Day");
student.setBirthDay("new Day");
student.setBirthPlace("new Day");
student.setScore(8f);
when(studentDAO.update(student)).thenReturn(false);
assertTrue(student == null);
}
#Test
public void deleteTest() {
when(studentDAO.delete(111005)).thenReturn(true);
Student stu = studentDAO.getStudentByStudentNumber(111005);
assertTrue(stu != null);
}
#Test
public void getAllStudentTest() {
List<Student> studentS = studentDAO.getAllStudent();
assertTrue(studentS.size() != 0);
}
#Test
public void getStudentByIdTest() {
}
}
where the error occurs
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.ids.demo.dao.StudentDAO com.ids.demo.test.Mockito.studentDAO; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.ids.demo.dao.StudentDAO] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:508)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289)
... 26 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.ids.demo.dao.StudentDAO] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1103)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:963)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:858)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:480)
... 28 more
Related
#Convert(converter = MsisdnEncryptor.class,disableConversion=true)
I have used this converter in my spring boot entity class.
package com.example.demo.entity;
This is the entity class:
#Entity
#Data
#AllArgsConstructor
#NoArgsConstructor
#Table(name="employee")
public class Employee {
#Id
#Column(name = "emp_id")
#SequenceGenerator(
name = "employee_sequence",
sequenceName = "employee_sequence",
allocationSize = 1
)
#GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "employee_sequence")
private Long EmpId;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(name = "mobile_number")
**#Convert(converter = MsisdnEncryptor.class,disableConversion=true)**
**here I want to put values from application.properties in disableConversion**
private String mobileNumber;
#Column(name= "date_time")
#JsonFormat(shape=JsonFormat.Shape.STRING, pattern="dd-MM-yyyy HH:mm:ss", timezone="GMT+5:30")
private Timestamp dateTime;
}
This is the Encryptor class:
#Component
public class MsisdnEncryptor implements AttributeConverter<String, String> {
private static final Logger logger = LoggerFactory.getLogger(MsisdnEncryptor.class);
#Value("${is.enabled:true}")
private boolean isEnabled;
private static final String AES = "AES";
private static final String SECRET = "secret-key-12345";
private final Key key;
private final Cipher cipher;
public MsisdnEncryptor() throws Exception {
key = new SecretKeySpec(SECRET.getBytes(), AES);
cipher = Cipher.getInstance(AES);
}
#Override
public String convertToDatabaseColumn(String attribute) {
try {
cipher.init(Cipher.ENCRYPT_MODE, key);
return Base64.getEncoder().encodeToString(cipher.doFinal(attribute.getBytes()));
} catch (IllegalBlockSizeException | BadPaddingException | InvalidKeyException e) {
throw new IllegalStateException(e);
}
}
#Override
public String convertToEntityAttribute(String dbData) {
try {
cipher.init(Cipher.DECRYPT_MODE, key);
return new String(cipher.doFinal(Base64.getDecoder().decode(dbData)));
} catch (InvalidKeyException | BadPaddingException | IllegalBlockSizeException e) {
throw new IllegalStateException(e);
}
}
}
I know we can use #Value for taking the values , but it doesn't work here as it says attribute value must be constant.
Or if there is any other way of doing the encryption and enabling/disabling it from config , I would be more than happy to go through it.
I'm using a Thymeleaf HTML registration form and simple save/update method to save/update a 'dish' object to a mySQL database. Restaurant Id is a foreign key for the 'dish' but using the below methods it saves as 'null',
I would like to make it so that the Restaurant id of the currently logged in restaurant owner saves automatically when they add a dish.
Is there an uncomplicated way to do this? The closest tutorial I've found on Youtube involves using JSON requests in Postman and I've had issue adapting that to a HTML registration form in the past.
I'm quite new to all of this so any help would be very much appreciated!
See Dish class:
package com.bron.demoJPA.appuser;
#Entity
#Data
#AllArgsConstructor
#NoArgsConstructor
#Builder
#ToString(exclude = "reqlist")
public class Dish {
#Id
#SequenceGenerator(name = "dish_sequence", sequenceName = "dish_sequence", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "dish_sequence")
#Column(name = "dish_Id")
private Long dishId;
#Column(name = "dish_name")
private String dname;
#Column(name = "dish_description")
private String description;
#Column(name = "dish_price")
private double price;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "Rest_ID", referencedColumnName = "Rest_ID")
private AppUser app;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "dish_requirment_mapping", joinColumns = #JoinColumn(name = "dish_Id", referencedColumnName = "dish_Id"), inverseJoinColumns = #JoinColumn(name = "Require_ID", referencedColumnName = "Require_ID"))
private List<Requirments> reqlist;
public void addRequirments(Requirments req) {
if (reqlist == null)
reqlist = new ArrayList<>();
reqlist.add(req);
}
}
See AppUser(restaurant owner) Class
#Column(name = "Rest_Password")
private String password;
#Column(name = "Rest_Email_Address")
private String email;
#Enumerated(EnumType.STRING)
private AppUserRole appUserRole;
private Boolean locked = false;
// don't enable user until email verification
private Boolean enabled = false;
public AppUser(String restname, String email, String pass, AppUserRole app) {
this.restaurantName = restname;
this.email = email;
this.password = pass;
this.appUserRole = app;
}
public Collection<? extends GrantedAuthority> getAuthorities() {
SimpleGrantedAuthority authority = new SimpleGrantedAuthority(appUserRole.name());
return Collections.singletonList(authority);
}
#Override
public String getUsername() {
return email;
}
#Override
public String getPassword() {
return password;
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return !locked;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return enabled;
}
#OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = true)
#JoinColumn(name = "openingHourID", referencedColumnName = "OpeningHour_ID")
private OpeningHour opening;
}
See Controller class:
package com.bron.demoJPA.conroller;
#Controller
public class DishController {
//display list of employees
#Autowired
private DishService dishService;
#GetMapping("/dish")
public String viewHomePage(Model model) {
model.addAttribute("listDish", dishService.getAllDish());
return "index";
}
#GetMapping("/showNewDishForm")
public String showNewDishForm(Model model) {
// Create model attribute to bind form data
Dish dish = new Dish();
model.addAttribute("dish", dish);
return "new_dish";
}
#PostMapping("/saveDish")
public String saveDish(#ModelAttribute("dish") Dish dish) {
// save dish to database
dishService.saveDish(dish);
return "redirect:/dish";
}
#GetMapping("/showFormForUpdate/{dishId}")
public String showFormForUpdate(#PathVariable(value = "dishId") long dishId, Model model) {
// get dish from service
Dish dish = dishService.getDishByDishId(dishId);
// set dish as model to pre-populate the form data
model.addAttribute("dish", dish);
return "update_dish";
}
}
See Service implementation
package com.bron.demoJPA.service;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.bron.demoJPA.appuser.Dish;
import com.bron.demoJPA.repository.DishRepository;
#Service
public class DishServiceImpl implements DishService {
#Autowired
private DishRepository dishRepository;
#Override
public List<Dish> getAllDish() {
return dishRepository.findAll();
}
#Override
public void saveDish(Dish dish) {
this.dishRepository.save(dish);
}
#Override
public Dish getDishByDishId(long dishId) {
Optional<Dish> optional = dishRepository.findById(dishId);
Dish dish = null;
if (optional.isPresent()) {
dish = optional.get();
} else {
throw new RuntimeException("Dish not found for: " + dishId);
}
return dish;
}
}
See Service class
public interface DishService {
List<Dish> getAllDish();
void saveDish(Dish dish);
Dish getDishByDishId(long dishId);
}
Can you make sure Dish's "app" attribute is being set correctly before trying to save it?
If it's null or it's a brand new instance of AppUser class it makes sense that when trying to match and persist it ends up on null.
Greetings!
I am attempting to connect to my database in a Spring MVC application. There are two tables. Users and Orders, Users has a primary key column: "userID", orders has a composite key from columns: "userID" and "orderID", where userID is a foreign key referencing the "userID" column in the Users table.
Here are my classes:
Order:
#Entity
#Table(name = "Orders")
#IdClass(OrderPK.class)
public class Order implements Serializable{
private static final Long serialVersionUID = 1L;
#EmbeddedId
private OrderPK orderPK;
//other properties
//no args and full args constructor
//getters and setters
//toString
}
OrderPK:
#Embeddable
public class OrderPK implements Serializable {
#Column(name = "orderID")
private Long orderID;
#ManyToOne
#JoinColumn(name = "userID")
private User user;
public OrderPK() {
}
public OrderPK(Long orderID, User user) {
this.orderID = orderID;
this.user = user;
}
public Long getOrderID() {
return orderID;
}
public void setOrderID(Long orderID) {
this.orderID = orderID;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof OrderPK)) return false;
OrderPK that = (OrderPK) o;
return Objects.equals(getOrderID(), that.getOrderID()) &&
Objects.equals(getUser(), that.getUser());
}
#Override
public int hashCode() {
return Objects.hash(getOrderID(), getUser());
}
}
User:
#Entity
#Table(name = "USERS")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#SequenceGenerator(name="USER_SEQUENCE", sequenceName="USER_SEQUENCE")
#GeneratedValue(strategy=GenerationType.SEQUENCE,
generator="USER_SEQUENCE")
#Column(name = "userid")
private Long userId;
//other properties
//no args and full args constructor
//getters and setters
//toString
}
When I try to connect to the database I get the following exception:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: Unable to find properties (orderID, user) in entity annotated with #IdClass:com.ex.evemarketback.domain.Order
...
Caused by: org.hibernate.AnnotationException: Unable to find properties (orderID, user) in entity annotated with #IdClass:com.ex.evemarketback.domain.Order
Any suggestions?
As you are using the #EmbeddedId, you do not need the #IdClass annotation:
#Entity
#Table(name = "Orders")
public class Order implements Serializable{
or if you want to keep the #IdClass:
// #Embeddable - no need for that
public class OrderPK implements Serializable {
private Long orderID;
private Long userId;
...
}
entity:
#Entity
#Table(name = "Orders")
#IdClass(OrderPK.class)
public class Order implements Serializable{
#Id
#Column(name = "orderID")
private Long orderID;
#Id
#Column(name = "userId", insertable=false, updatable=false)
private Long userId;
#ManyToOne
#JoinColumn(name = "userID")
private User user;
I try to display data from my database, but I get 500 error page: javax.ejb.EJBException. I don't understand why it's not working. Maybe my Bean is wrong? Please help me.
Warning in Glassfish log: WARNING: WARNING: EJB5184:A system exception occurred during an invocation on EJB SearchBean, method: public java.util.Collection com.stark.logic.SearchBean.searchByNumber(int)
#Entity
#Table(name = "buy")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Buy.findAll", query = "SELECT b FROM Buy b"),
#NamedQuery(name = "Buy.findByIdBuy", query = "SELECT b FROM Buy b WHERE b.idBuy = :idBuy"),
#NamedQuery(name = "Buy.findByNumberBuy", query = "SELECT b FROM Buy b WHERE b.numberBuy = :numberBuy")})
public class Buy implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id_buy")
private Integer idBuy;
#Basic(optional = false)
#NotNull
#Column(name = "number_buy")
private int numberBuy;
#OneToOne(cascade = CascadeType.ALL, mappedBy = "buy")
private Product product;
#OneToOne(cascade = CascadeType.ALL, mappedBy = "buy")
private Client client;
//getters & setters
EJB BEAN:
#Stateless
#LocalBean
public class SearchBean {
#PersistenceUnit
EntityManagerFactory emf;
EntityManager em;
public Collection searchByNumber(int number){
em = emf.createEntityManager();
Query searchQuery = em.createNamedQuery("Buy.findByNumberBuy");
searchQuery.setParameter("number_buy", number);
List list = new ArrayList();
list = searchQuery.getResultList();
return list;
}
}
Servlet:
#EJB
private SearchBean searchBean;
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
response.setContentType("text/html;charset=UTF-8");
String num = request.getParameter("number");
int number = Integer.parseInt(num);
List list = new ArrayList();
list = (List) searchBean.searchByNumber(number);
Iterator it = list.iterator();
while(it.hasNext()){
Buy buy = (Buy) it.next();
out.println(buy.getProduct());
}
}
Parameter name in #NamedQuery and in setParameter() method must be equal:
searchQuery.setParameter("numberBuy", number);
I have the following class:
#PersistenceCapable(identityType = IdentityType.APPLICATION, detachable = "true")
public class TclRequest implements Comparable<TclRequest> {
#PrimaryKey
private String id;
#Persistent(types = { DNSTestData.class, POP3TestData.class, PPPoETestData.class, RADIUSTestData.class }, defaultFetchGroup = "true")
#Columns({ #Column(name = "dnstestdata_fk"), #Column(name = "pop3testdata_fk"), #Column(name = "pppoetestdata_fk"), #Column(name = "radiustestdata_fk") })
private TestData testData;
public String getId() {
return id;
}
public TestData getTestData() {
return testData;
}
public void setId(String id) {
this.id = id;
}
public void setTestData(TestData testData) {
this.testData = testData;
}
}
The TestData interface looks like this:
#PersistenceCapable(detachable = "true")
public interface TestData {
#PrimaryKey
public String getId();
public void setId(String id);
}
Which is implemented by many classed including this one:
#PersistenceCapable(detachable = "true")
public class RADIUSTestData implements TestData {
#PrimaryKey
private String id;
private String password;
private String username;
public RADIUSTestData() {
}
public RADIUSTestData(String password, String username) {
super();
this.password = password;
this.username = username;
}
#Override
public String getId() {
return id;
}
#Override
public void setId(String id) {
this.id = id;
}
}
When I try to persiste the TclRequest class, after constructing it of course and using the RADIUSTestData:
//'o' is the constructed TclRequest object.
PersistenceManager pm = null;
Transaction t = null;
try {
pm = getPM();
t = pm.currentTransaction();
t.begin();
pm.makePersistent(o);
t.commit();
} catch (Exception e) {
e.printStackTrace();
if (t != null && t.isActive()) {
t.rollback();
}
} finally {
closePM(pm);
}
The interface field isn't persisted. And the column is not created in the table ! I enabled the debug mode and found 2 catchy things:
1)
-Class com.skycomm.cth.beans.ixload.radius.TestData specified to use "application identity" but no "objectid-class" was specified. Reverting to javax.jdo.identity.StringIdentity
2)
-Performing reachability on PC field "com.skycomm.cth.beans.TclRequest.testData"
-Could not find StateManager for PC object "" at field "com.skycomm.cth.beans.TclRequest.testData" - ignoring for reachability
What could this mean ?
Thanks in advance.
I have figured out how to do it. It's not very much scalable but it works for now.
These are the annotations for the interface member variable. Note that the order of declared types, columns and class names in the extension value is important to be maintaned:
#Persistent(types = { RADIUSTestData.class, POP3TestData.class, PPPoETestData.class, DNSTestData.class }, defaultFetchGroup = "true")
#Columns({ #Column(name = "radiustestdata_fk"), #Column(name = "pop3testdata_fk"), #Column(name = "pppoetestdata_fk"),
#Column(name = "dnstestdata_fk") })
#Extension(vendorName = "datanucleus", key = "implementation-classes", value = "com.skycomm.cth.tcl.beans.radius.RADIUSTestData, com.skycomm.cth.tcl.beans.pop3.POP3TestData, com.skycomm.cth.tcl.beans.pppoe.PPPoETestData, com.skycomm.cth.tcl.beans.dns.DNSTestData")
A sample class implementing one of the interfaces (Just it's "header"):
#PersistenceCapable(detachable = "true")
public class RADIUSTestData implements TestData {
So it's pretty normal here.