Use #RequestParam for DTO fields implicitly - spring-mvc

Controller
#RequestMapping(method = RequestMethod.GET)
public ResponseEntity<PaginatedResponse<User>> getAllUsers(
#RequestParam(defaultValue = "") String q,
#RequestParam(defaultValue = "") String[] fields,
#RequestParam(defaultValue = "") String[] sort,
#RequestParam(defaultValue = "50") Integer limit,
#RequestParam(defaultValue = "0") Integer offset,
#RequestParam(defaultValue = "") String userField1,
#RequestParam(defaultValue = "") String userField2,
#RequestParam(defaultValue = "") Boolean userField3,
#RequestParam(defaultValue = "") ZonedDateTime userField4,
#RequestParam(defaultValue = "") String userRoleId5,
#RequestParam(defaultValue = "") Long userRoleId6,
#RequestParam(defaultValue = "") Long userRoleId7
) {
//call to service
}
UserDTO
public class UserDTO {
private String userField1;
private String userField2;
private boolean userField3;
ZonedDateTime userField4;
#JsonProperty("USERFIELD5")
private String userField5;
#JsonProperty("USERFIELD6")
private Long userField6;
#JsonProperty("USERFIELD7")
private Long userField7;
//getters and setters
}
user fields are used in GET /users parameter to filter the list of users in response. The current code works but I'm wondering if there is a better way to avoid this manual definition of the fields in the controller.
I considered using HahsMap to get all the request parameters but I opt out since I need to check if the passed parameter is valid.

Use #ResponseBody like
#ResponseBody
#RequestMapping(value = "your mapping here", method = RequestMethod.GET)
public List<User> getUsers() {
}
and serialize your User entity attributes with Jackson or GSON w/e
With gson you can serialize your fields like
#SerializedName("user_id")
private Integer id;

Related

Spring Boot "Cannot add foreign key constraint"

I have a spring boot rest service with the following model classes -
Report class -
#Entity
#Table (name = "report")
#EntityListeners(AuditingEntityListener.class)
public class Report {
#Id
#Column (name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "from_user_id", nullable = false)
private Long fromUserId;
#Column(name = "to_user_id", nullable = false)
private Long toUserId;
#Temporal(TemporalType.DATE)
#JsonFormat(pattern = "dd-MM-yyyy hh:mm:ss")
#CreatedDate
private Date createdAt;
#Column(nullable = false)
private String observation;
[ OTHER VARS AND GETTERS AND SETTERS .... ]
}
User class -
#Entity
#Table (name = "user")
#EntityListeners(AuditingEntityListener.class)
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class User {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(nullable = false)
private String firstName;
#Column(nullable = false)
private String lastName;
#Column(unique = true, nullable = false)
private String email;
#Column(nullable = false)
private String password;
#OneToMany(cascade = CascadeType.ALL, targetEntity = Report.class)
#JoinColumn(name = "to_user_id")
private List<Report> reportReceivedList;
#OneToMany(cascade = CascadeType.ALL, targetEntity = Report.class)
#JoinColumn(name = "from_user_id")
private List<Report> reportSentList;
[GETTERS AND SETTERS .....]
}
This is causing a
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL via JDBC Statement
which in turn is caused by
Caused by: java.sql.SQLException: Cannot add foreign key constraint
I want to create my mapping such that one user can have multiple sent reports and received reports, and once I delete a user, both sent and received reports should get deleted. I have explored loads of links for creating mappings and I am very confused because of different methods given everywhere.

Hibernate cannot simultaneously fetch multiple bags for Parent-Children-Grandchildren unidirectional association

Straightforward to the point. I am given Hibernate exception Caused by: org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags.
I have 3 entities in a Parent --(1-*)--> Child --(1-*)--> Grandchild unidirectional relationship:
NetworkElement -> NetworkElementInterface -> NetworkElementInterfaceCounters
Over both relationship I have defined FetchType.LAZY.
#Entity
#Table(name = "NETWORK_ELEMENTS")
public class NetworkElement extends Device {
#Id
#Column(name = "ID_DEVICE")
private Long id;
#ManyToOne(targetEntity = DeviceLocation.class, fetch = FetchType.LAZY)
#JoinColumn(name = "ID_DEVICE_LOCATION")
private DeviceLocation deviceLocation;
#Column(name = "MODEL", length = 30)
private String model;
#Column(name = "TYPE", length = 30)
private String type;
#Column(name = "IMAGE", length = 50)
private String image;
#OneToMany(orphanRemoval = true, fetch = FetchType.LAZY, targetEntity = NetworkElementInterface.class, cascade=CascadeType.ALL)
#Size(min = 0, max = 99)
private List<NetworkElementInterface> interfaces;
}
#Entity
#Table(name = "NETWORK_ELEMENT_INTERFACES")
public class NetworkElementInterface {
#Id
#Column(name = "ID_NETWORK_ELEMENT_INTERFACES")
protected Long id;
#Column(name = "NAME")
private String name;
#Column(name = "SPEED")
private Long speed;
#Column(name = "DUPLEX")
private String duplex;
#ElementCollection(fetch = FetchType.LAZY)
#CollectionTable(name = "NETWORK_ELEMENT_INTERFACE_COUNTERS", joinColumns = #JoinColumn(name = "ID_NETWORK_ELEMENT_INTERFACE"))
#Type(type = "com.netsuite.wind.entity.NetworkElementInterfaceCounters")
private List<NetworkElementInterfaceCounters> interfaceCountersHistory;
}
#Embeddable
public class NetworkElementInterfaceCounters {
private Long inputErrors;
private Long inputDrops;
private Long inputDiscards;
private Long inputCRCErrors;
private Long inputFifoErrors;
private Long outputErros;
private Long outputDrops;
private Long outputCRCErrors;
private Long outputFifoErrors;
}
What I am trying to achieve is:
1) in my DAO to create a method which will return Parent fully populated with its children and grandchildren. (NetworkElement -> NetworkElementInterface -> NetworkElementInterfaceCounters).
1b) (not really important here, just curious) Eventually I would also like to populate children of a different type, in my NetworkElement DeviceLocation object along with populated NetworkInterfaces.
My DAO Method of NetworkElement:
#Transactional()
#SuppressWarnings("unchecked")
public NetworkElement getByIdWithInterfaces(Long id) {
final Session session = sessionFactory.getCurrentSession();
------------------------------------------------------
// This works well when I only want children to by populated
Query query = session.createQuery("SELECT ne FROM NetworkElement ne JOIN FETCH ne.interfaces WHERE ne.id = :id");
------------------------------------------------------
// This doesn't work when I also try to fetch grandchildren. I am given Hibernate exception: "cannot simultaneously fetch multiple bags"
Query query = session.createQuery("SELECT ne FROM NetworkElement ne JOIN FETCH ne.interfaces nei JOIN FETCH nei.interfaceCountersHistory WHERE ne.id = :id");
------------------------------------------------------
// Eventually I tried "FETCH ALL PROPERTIES" which also doesn't work.
Query query = session.createQuery("FROM NetworkElement ne FETCH ALL PROPERTIES WHERE ne.id = :id");
------------------------------------------------------
query.setParameter("id", id);
NetworkElement result = null;
try {
result = (NetworkElement) query.uniqueResult();
} catch (NoResultException e) {
e.printStackTrace();
}
return result;
}
So for:
1) Query query = session.createQuery("SELECT ne FROM NetworkElement ne JOIN FETCH ne.interfaces nei JOIN FETCH nei.interfaceCountersHistory WHERE ne.id = :id");
Try to make it work.
I think I am missing somewhere some annotation in order to avoid this kind of exception. I noticed in some examples they were using #IndexColumn but this annotation is deprecated.. Appreciate any directions for this.

Spring-Security DAOAuthenticationProvider asks for ID for authentication

I am using Spring-Security on top of a Spring-MVC application. I have my own implementation of UserDAO, userDetailsService. I am trying to authenticate by checking from database(ofcourse). I reach till the login page, everything seems to be working fine, but when I login, I get an error :
ERROR:
org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter - An internal error occurred while trying to authenticate the user.
org.springframework.security.authentication.InternalAuthenticationServiceException: Provided id of the wrong type for class com.WirTauschen.model.User. Expected: class java.lang.Integer, got class java.lang.String
at org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:110)
I do not know where am I retrieving or working with user's id. I am posting the code below.
LoginService :
#Service("userDetailsService")
public class LoginServiceImpl implements UserDetailsService{
#Autowired private UserDao userDao;
#Autowired private Assembler assembler;
#Override
#Transactional
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserDetails userDetails = null;
User user = userDao.findByName(username);
if(user == null) { throw new UsernameNotFoundException("Wrong username or password");} //Never specify which one was it exactly
return assembler.buildUserFromUserEntity(user);
}
}
Assembler
#Service("assembler")
public class Assembler {
#Transactional(readOnly = true)
User buildUserFromUserEntity(com.WirTauschen.model.User userEntity){
String username = userEntity.getUsername();
String password = userEntity.getPassword();
// int id = userEntity.getId();
boolean enabled = userEntity.isActive();
boolean accountNonExpired = userEntity.isAccountNonExpired();
boolean credentialsNonExpired = userEntity.isCredentialsNonExpired();
boolean accountNonLocked = userEntity.isAccountNonLocked();
Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
User user1 = new User(username,password,enabled,accountNonExpired,credentialsNonExpired,accountNonLocked,authorities);
return user1;
}
}
User :
#Entity
#Table(name="registration")
public class User implements UserDetails{
private static final GrantedAuthority USER_AUTH = new SimpleGrantedAuthority("ROLE_USER");
#Id
#Column(name="id")
private String id=UUID.randomUUID().toString();
// #GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "my_entity_seq_gen")
//#SequenceGenerator(name ="my_entity_seq_gen", sequenceName = "MY_ENTITY_SEQ")
#OneToMany
private Set<ProductBasic> productBasic;
#Column(name = "email")
private String email;
#Column(name = "username")
private String Username;
#Column(name = "displayname")
private String DisplayName;
#Column(name = "password")
private String password;
#Column(name = "companyname")
private String CompanyName;
#Column(name = "firstname")
private String FirstName;
#Column(name = "middlename")
private String MiddleName;
private String role="ROLE_USER";
#Transient
private final String PERMISSION_PREFIX = "ROLE_USER";
#Transient
private List<GrantedAuthority> authorities;
public User() {
this.authorities = new ArrayList<GrantedAuthority>();
authorities.add(USER_AUTH);
}
public User(String Username, String password, String Role){
this.Username = Username;
this.password = password;
this.role = Role;
if((role == null) || role.isEmpty()){ role = "ROLE_USER";}
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
Update sequence code
#Id
#Column(name = "sortcanvasid")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sortcanvas_gen")
#SequenceGenerator(name = "sortcanvas_gen", sequenceName = "sortcanvas_seq")
private int sortCanvasId;
Seems that your User class not implementing UserDetails Morever it might not be having proper return type of the getID method

Unable to serialize custom object activeandroid

I am trying to store some custom object as a blob in SqlLite db. The object is a field of a class extending Model. All other fields (of primitive types) go successfully in the DB, but the custom one - it is null always.
#Table(name = "data")
public class Data extends Model {
#Column(name = "number")
private int number;
#Column(name = "blob")
private Contact blob;
...
This is how i store the entity
Data data = new Data(0, new Contact(id, name, number));
data.save();
Here is the contact class
public class Contact {
private String id;
private String name;
private String number;
...
I believe a TypeSerializer is needed, so I've created one.
public class ContactSerializer extends TypeSerializer {
private static final String ELEMENTS_DELIMITER = ";";
#Override
public Object deserialize(Object asString) {
String[] afterSplit = ((String) asString).split(ELEMENTS_DELIMITER);
return new Contact(afterSplit[0], afterSplit[1], afterSplit[2]);
}
#Override
public Class<?> getDeserializedType() {
return Contact.class;
}
#Override
public SerializedType getSerializedType() {
return SerializedType.STRING;
}
#Override
public Object serialize(Object asContact) {
Contact temp = (Contact) asContact;
return temp.getId() + ELEMENTS_DELIMITER + temp.getName() + ELEMENTS_DELIMITER
+ temp.getNumber();
}
}
When i query the db I got object with this particular field "Contact" as null always. Where might be the problem? Do I need to specify which is the TypeSerializer for my object? Or the implementation of TypeSerializer I've created is wrong?
You also need to extent Contact from Model:
#Table(name = "contact")
public class Contact extends Model{
#Column(name = "id")
private String id;
#Column(name = "name")
private String name;
#Column(name = "number")
private String number;
}
Now everything should work out of the box. It's a bit late for a response but perhaps I will help someone else.

Try to show data from db using JPA and EJB

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);

Resources