I made a single Java Application using Tomcat(Prod) and Jetty(Dev) + Hibernate + Spring + Spring MVC + Fremarker
I have a issue to solve, 'cause the users are reporting that only one user can do login without conflict. If a user does login and tries to create a new entity Payment, he have a successfull transaction. But when another user does login, since then, nobody can create a new Payment.
There is no exception, a POST is executed, but seems like the Controller is not able for delivery the form to services classes.
#MappedSuperclass
#Getter
#Setter
public abstract class AbstractEntity implements Persistable, Cloneable {
//code...
}
#Entity
#Getter
#Setter
public class Pagamento extends AbstractEntity{
//code...
}
#Component
#Transactional
public class PagamentoService {
//code...
}
#Controller
#RequestMapping("/payments")
public class PagamentosController {
//code...
}
Is everything okay about Annotations and CDI? What could to be happening?
A common use case for that is using attributes of controller (or service, dao, etc.) classes. All those beans are singleton beans and are shared between all requests and sessions. You should only use local variables in all those singleton beans - except of course for attributes that are common for the whole application ...
Can it be because you are using a single-connection DataSource, so once a request takes a connection then no other requests can access it until the first one releases the one-and-only database connection.
Related
I have the #Controller, #Service and #Repository classes.
The application works fine, but I think I'm not using the annotations properly for the "entity" and "repository" classes.
I'm actually not using a db(not even an in-memory db) and don't intend to.
I'm currently annotating the repository with #Repository and the entities with #Service and this is my concern: am I doing this correctly?
How should I design and use the Spring annotations to wire the entity and repository classes to the service if I don't want to persist the data?
Currently it looks like this:
Service class
#Service
public class ServiceClass{
#Autowired
RepositoryClass repositoryClass;
public ServiceClass(RepositoryClass repositoryClass) {
this.repositoryClass = repositoryClass;
}
}
Repository class
#Repository
public class RepositoryClass{
#Autowired
private Entity entity;
public DocumentRepository(Entity entity) {
this.entity = entity;
}
}
Entity class
#Service
public class Entity {
private Map<String, List<Integer>> entityMap;
public Entity (Map<String, List<Integer>> entityMap) {
this.entityMap = entityMap;
}
}
Annotating an entity class with #Service is wrong.
A class annotated with #Service is usually stateless, and for that reason, there is usually only one object of such a class.
A class annotated with #Entity is usually stateful, and for that reason, there are usually many objects of such a class.
An example scenario is a simple news service:
There is one NewsService that contains interesting code to fetch news from the repository.
For each news item, there is a NewsEntity object, holding the data of the individual news item.
The question is: what's the role of each class here. Usually a repository is the point to access data. An entity is a data object, not a logic component, so it is usually created and managed by the repository, in this example, not Spring.
It's hard to firmly say anything with only that code (no information about how every component is used), but I would remove the #Service from the Entity class. The other classes are ok with those annotations.
You can't use #Entity from data-jpa w/o setting up some db, so your entities don't need any annotation. They aren't beans that you need to wire in anywhere.
But the general idea that 'when you don't know' it's probably a service is a good one. XD
The other annotations are right.
You can basically annotate them with #Component, #Service, #Config, #Repository ... It wouldn't break your code, the names are mostly just to be more clear for the people working on the code.
I created a user management service based on springboot.
The user will have a list of attachments, so the relationship of the user and attachment is OneToMany.
I ignored the insert logic here since my question is about the lazyload and when the entitymanager is opened and closed. Below is the entity, controller, service, dao, repository related code.
Entity
#Entity
#Table(name="User")
public class UserInfoEntity {
private long id;
private String mail;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "userInfoEntity", cascade = CascadeType.ALL)
private List<UserAttachmentEntity> attachmentList = new ArrayList<>();
}
#Entity
#Table(name = "ATTACHMENT")
public class UserAttachmentEntity {
private long id;
private String name;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="userRequestId")
private UserInfoEntity userInfoEntity;
}
Service
#Service
public class UserServiceImpl implements UserService {
#Autowired
private UserDao userDao;
#Override
#Transactional
public void save(UserInfoEntity userInfoEntity) throws RestException {
userDao.save(userInfoEntity);
}
#Override
// I did set #Transactional here
public UserInfoEntity findByMail(String mail) {
UserInfoEntity userInfoEntity = userDao.findByMail(mail);
return userInfoEntity;
}
}
DAO
#Service
public class UserDaoImpl implements UserDao {
#PersistenceContext
private EntityManager entityManager;
#Autowired
private UserInfoEntityRepository userInfoRepository;
#Override
public UserInfoEntity findByMail(String mail) {
return userInfoRepository.findFirstByMailOrderByIdDesc(mail);
}
}
Repository
#Repository
public interface UserInfoEntityRepository extends JpaRepository<UserInfoEntity, Integer> {
UserInfoEntity findFirstByMailOrderByIdDesc(String mail);
}
Controller
#Controller
#RequestMapping(value = "/user")
public class UserController {
#RequestMapping(value = "load", method = RequestMethod.POST)
#ResponseBody
public UserInfoEntity load(UserInfoEntity userInfoEntityInput, HttpServletRequest request) throws Exception {
UserInfoEntity userInfoEntity = userService.findByMail(userInfoEntityInput.getMail());
System.out.println(userInfoEntity.getAttachmentList());
return userInfoEntity;
}
}
After I test the load method in controller, I found that even I set the
#OneToMany(fetch = FetchType.LAZY,...) in
UserInfoEntity.
I can still call userInfoEntity.getAttachmentList() in controller.
(I can see the select * from attachment query was printed there)
The answer of the post lazyinitializationexception-in-spring-data-jpa said that you need to fetch the lazy data while you are inside of a transaction.
But I did not set the #Transaction in the findByMail method in service.
And I remember that I also met this exception a couple of days ago. But now I can load the lazy data successfully in controller.
I mainly have below questions.
When the entitymanager is opened and closed? (is it opened in service or dao?)
Why the lazy data can be loaded in controller?
Is the entity manager thread-safe? (I googled, but not find useful answer)
Is the entity manager singleton? ( in above code, I inject the entity manager into dao, although I did not use it, I used spring data, I can inject the entity manager to service, controller, find the hashcode is different)
Thanks in advance. I wrote this question in company, I was not allowed to push any code to github in company. If I can, I think it will be more convenient for you since the spring boot project with h2 database is very easy to setup locally.
Spring Boot JPA Opens Session in View by default
If you go along the Appendix A. Common application properties, you will find by default Spring boot defines
spring.jpa.open-in-view=true
That actually register OpenEntityManagerInViewInterceptor. Binds a JPA EntityManager to the thread for the entire processing of the request.
This actually leads to confusion, See this issue reported by the community.
When the EntityManager is opened and closed?
Basically, an EntityManager opens a transaction where #Transaction annotation is declared or in your case it is opened by the OpenEntityManagerViewInterceptor on every request and that stays open before the response is made.
Is the entity manager thread-safe?
NO. Its not threadsafe, but the EntityManagerFactory is. And EntityManager is obtained from EntityManagerFatory. Hence an EntityManager is inexpensive and expected to be used once for a single unit of work. Where An EntityManagerFactory is typically created at application initialization time and closed at the application end. See Hibernate doc for details about Obtaining an EntityManager in a Java SE environment
Is the entity manager singleton?
No. EntityManager is an interface, and what gets injected in the spring bean when you autowire, is not the entity manager itself but a context-aware proxy that will delegate to a concrete entity manager at runtime. Usually, the concrete class used for the proxy is SharedEntityManagerInvocationHandler
For more detail explanation about how the whole JPA transaction go around. I recommend reading this How Does Spring #Transactional Really Work?
In Spring Boot the Open Session In View is enabled by default which means that you don't have to use #Transaction in your code unless it is required by your app's logic.
However, note that the enabled OSIV is considered as bad practice - the detailed debate about this topic can be found at https://stackoverflow.com/a/37526397/3750108
I'm hoping someone could shed some more light on my confusion with JPA entities in a Spring Boot project. I've heard that one should never call new in a Spring project. I understand that this is to allow Spring to manage all of the beans, and getting a bean can be done through injection or through the application context explicitly.
However, it's not clear to me how to get a new JPA Entity. If I have a class annotated with #Entity and a repository class that handles my data access, how do I obtain a new entity object in my service layer?
I've included #EntityScan in my application's main class so I would assume that Spring is aware of the entity. But when I try to get it through the ApplicationContext an exception is raised. This makes sense because I don't believe the #Entity annotated classes are Spring Beans, and I don't think it would be correct to also annotate it with #Component. Any clarification would be greatly appreciated.
I'm currently using the new keyword and creating the entity objects myself in the service layer. A very simple example is below:
entities/User.java
#Entity
#Table(name = "users")
public class User {
#Id
private Long id;
private String username;
// Getters & Setters ...
}
repositories/UserRepository.java
#Repository
public interface UserRepository extends CrudRepository<User, Long> {
User findByUsername(String username);
}
services/UserServiceImpl.java
#Service
public class UserServiceImpl implements UserService {
UserRepository userRepository;
#Autowired
public UserServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
public void createAndSaveUser(String username) {
User user = new User();
user.setUsername(username);
userRepository.save(user);
}
}
And we could assume that there was some other controller classes that would utilize the service layer.
In this example I am explicitly calling the new keyword in the service class method createAndSaveUser. Is this the correct way to do it or should I be getting some prototype bean from Spring that maps to my JPA entity?
In spring you can autowire/inject your beans, components or services. However the entity should not be autowired since these interactions are done through your repository. Your repository can be autowired.
When you want to create a new instance of your entity you are allowed to call new, because this does not need to be managed by spring. You can simply use the autowired repository to save it in the database. This also works the other way around because obviously you would need the autowired repository to retrieve your entity.
So yes, your method is correct.
I hope this makes it clearer for you, if you have any questions feel free to ask :)
Whatever you are doing is completely valid in spring. In example you have provided above I could figure out that you want your entity class object itself to store the values. Its absolutely correct.
You have to use new keyword to achieve that.
If you still wish to not create a new object for your Entity you have another option to do it through Bean/POJO/VO classes and mapping your entity object with these classes.
But Still i will tell that whatever you have done is completely fine.
Actually the object you are creating is for storing value purpose not just because you have some method is there in your class and so you are bound to create new Object to be able to call that method(As we do in normal java project).In spring that is handle by #Autowired annotation to create object.
Simple example is you will be auto-wiring your repositories in your service classes.
I hope this help.
It sounds good to me: you create your entity and then ask the repository to store it.. no problem with Spring.
have you checked this out? :
http://spring.io/guides/gs/accessing-data-jpa/
have fun
Using: EJB 3.1, JBoss AS 7, RestEasy.
I have a session scoped bean which I want to user to store user informations for the session.
import java.io.Serializable;
import javax.enterprise.context.SessionScoped
#SessionScoped
public class LoggedInUser implements Serializable {
private String id;
...
}
If the user open my web application a filter extract header informations (application runs behind a webseal) which contains a user identification. I need to create a logged in user object (see LoggedInUser above) there (after calling ldap). Afterwards I want to inject this LoggedInUser object in different #Stateless Beans, but LoggedInUser is always "empty" (members are null).
Inject sample:
#Path("/country")
#Stateless
public class CountryController extends AbstractController {
#Inject
private Logger LOGGER;
#Inject
private LoggedInUser loggedInUser;
//#Inject dont work too..
//private Instance<LoggedInUser> loggedInstance
What do Im wrong?
Judging by the comment and the question - you need some help with EJB concepts.
#SessionScoped beans are beans that have one instance per session. Every #Inject with bean like that during one session will reference the same object. That's it however - if you want your bean to contain some information specific to that session, you will need to put it there yourself, using setters or other methods like you would do in every normal Java class.
Can you please tell me how is best to do?
How can I create a new instance of an entity on web application if I have only the interface..
I have :
EJB(3.1) Project
Web project
I have an EJB Project like:
User.java
#Entity
public class User {
//variables.. getters and setters...
}
UserManagerBean.java
#Stateful
public class UserManagerBean implements UserManager {
//getters and setters...
//.......
public void addUser(User user) {
//implemented here
}
//.......
}
UserManager.java
#Local
#Remote
public interface UserManager {
//methods here
}
In the web application(a standalone web application) I have this:
UserManager.java
public interface UserManager {
//methods here
}
User.java
public interface User {
//methods here
}
Now.. in a bean... I am trying to get from the remote context my beans and use them:
//ctx is created with the specific properties to access remote context..
InitialContext ctx = new InitialContext();
userManager = (UserManager)ctx.lookup("java:global/project/projectEJB/UserManagerBean");
User user = userManager.getUserById(1); //working
User new_user = (User)ctx.lookup("java:global/project/projectEJB/User"); //not working
//I know this is not supposed to work.. but how can I do this?
I know you can't get an instance of an entity because it's not an ejb...
Do I have to create a normal class of user having everying as on projectEJB? isn't there a better solution?
What other solutions are there? I searched for google and it seems like everybody knows how to do this.. only I don't...
Thank you in advance..
To create the User object you just create a regular Java instance with the 'new' operator and then invoke your EJB call.
User myNewUser = new User();
userManager.addUser(myNewUser);
Both the client side (your web application) and the server side (EJB 3.1 project) must know how to serialize and deserialize the User object therefore each side must have access to the User class and the EJB interfaces.
In terms of packaging you could bundle the EJB interface and User entity class all into a single JAR that is used by both the client and server sides.
An alternative deployment would be to bundle the web app and EJB into a single application deployed inside the same JVM.
Entity beans are not supposed to be created directly in web layer — because for making them persistent them you need the EntityManager, which is not guaranteed to be thread safe (and that's important in a servlet context).
What you probably want to do is writing a DAO EJB with a method to create a new user, inject/look it up in the servlet, and call it. Google for "GenericDAO" pattern to start with.