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.
Related
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.
I'm creating a java class library and EJB module as a user authentication application which can be used by stand alone clients by calling the remote interface EJB and its implementation class (session bean). I'm Using Netbeans 8 and Glassfish 4.0. After succesfully building the app I get the following stack when trying to run it:
SEVERE: Exception during lifecycle processing
java.lang.Exception: java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: java.lang.RuntimeException: java.lang.NoClassDefFoundError: Lcom/manaar/security/services/remote/UserServiceRemote;
at com.sun.enterprise.web.WebApplication.start(WebApplication.java:168)
at org.glassfish.internal.data.EngineRef.start(EngineRef.java:122)
at org.glassfish.internal.data.ModuleInfo.start(ModuleInfo.java:291)
at org.glassfish.internal.data.ApplicationInfo.start(ApplicationInfo.java:352)
...
SEVERE: Exception while loading the app : java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: java.lang.RuntimeException: java.lang.NoClassDefFoundError: Lcom/manaar/security/services/remote/UserServiceRemote;
The steps I'm following are:
1) Create the Java class library and populate it with the remote interface and entity class
2) Create the EJB module and populate this with the implementation class (session bean) and dao methods
3) Add both projects above to the library of the client JSF web application
4) Call the remote interface as an EJB in the client app and use the methods to show a user profile
The main classes are:
1) Java class library
#Remote
public interface UserServiceRemote {
public List<Users> findAllUsers();
public Users findByName(String userName);
public void createUser(Users newUser);
public void updateUser(Users updatedUsers);
public void deleteUser(Users userToDelete);
public void adminUpdateUser(Users aUpdatedUser);
#Entity
#Table(name = "SHA_USERS")
public class Users {
#Id
private String userName;
private String password;
2) EJB Module
#Stateless
public class UserServiceImpl implements UserServiceRemote {
#EJB
private UsersDao dao;
#Override
public Users findByName(String userName) {
return dao.findByName(userName);
}
3) Java class library and EJB module are both added as Projects in the client application
4) The managed bean in the client app:
#ManagedBean
#SessionScoped
public class SecClientFull {
#EJB
private UserServiceRemote useServ;
private Users loggedUser;
private String userName;
public String showProfile() {
loggedUser = useServ.findByName(userName);
return "/Users/AppUserProfile";
}
public String getUserName() {
userName = FacesContext.getCurrentInstance().getExternalContext().getRemoteUser();
return userName;
}
...
}
Looking in this forum and elsewhere online I've seen several posts talking about bug in GF3. I'm using the newest version so I'm hoping this is not a bug and I have simply configured this wrong.
Also I'm not clear if I still need to add any configurations for the EJBs in the glassfish-web.xml (or sun-web.xml) configuration file. I've assumed that the Java EE annotations are sufficient.
Finally I should say I coded this manually. I'm not sure if using the Netbeans wizards to create the libraries and session beans is a better way to make sure the configurations are correct.
Would really appreciate any advice or feedback and pls let me know if I need to provide further information. Thanks in advance!
The solution to the above is twofold:
1) Make sure that both Java class library and EJB module are created with separate 'lib' directories if they are to used by stand alone applications (which they are in my case). It's easy to overlook that point if you're creating EJBs for use in the same app (as many tutorials are)
2) The entity class (Users) must implement the java.io.Serialization interface and so should the managed bean on the client side
When first re-creating the Java class library and EJB module I got a ClassCastException that Users cannot be cast to Serialization. As the Java EE tutorial says the implementation of Serialization is for security reasons when EJB modules are used by stand alone applications and transferred accross networks.
So I added the interface to the entity class and the managed bean on the client side. The exception was eliminated and the app now runs perfectly. Thanks again!
Did you create default no args constructor for your class. Because I don't see it in your code.
I am new to Java EE so my question may be very basic. I have built following REST web service with Stateless session bean (simplyfied):
#Path("/list/")
#Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
#Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
#Stateless
public class ListResource {
#PersistenceContext(unitName = "unitName")
private EntityManager em;
#GET
#Path("/")
public List<Compound> getCompounds() {
List<Compound> list = tq.getResultList();
if (list.isEmpty()) {
throw new WebApplicationException(Response.status(404).entity("There are no compounds in database.").build());
}
return list;
}
}
It works like charm. Its accessible via URL and return JSON. Problem is that I have another part of the program written in plain Java that needs to use this Session bean as some kind of model to get all Compounds.
Problem is that when I initialize this Session bean somewhere it is outside of persistence context and therefore doesnt know EntityManager to access database. I believe.
I dont know what to do. Can I initialize class ListResource in distant part of code and have Dependency injection of EntityManager working? Or somehow to get persistence context and then initialize this session bean?
I hope it makes sense. Its complicated problem for me to describe.
If you have a web service and a standalone app calling the same bean, I would recommend you to move the functionality in a separate stateless bean and create remote and local interfaces to it. This way you can inject local bean into you web service bean, and call the remote one with jndi.
More about accessing Java EE beans here.
Alternatively, your client java code can call the web service to get all the data. Refer to this question about ways to connect to a RESTful service.
#Local
public interface EJBA{
// declares a method 'validate'
}
#Stateless
public class EJBABean implements EJBA{
// implements the method 'validate'
}
class Model{
#EJB
private EJBA ejbA;
public void doSomething(){
ejbA.validate();
}
}
Now, if I do the following from the execute method of a Struts 1.2 action class
new Model().validate();
ejbA of Model is null, resulting in a NullPointerException. The question is similar to this but, in my case, I am running the client code (Model) as well as the bean in the JBoss 6.1 Final server itself. The model and the EJB are in the a separate jar file and the the action classes are in a war file. Both of these are packaged inside an ear file.
If I use a context lookup using [ear-name]/EJBABean/local, I am able to access it though. What am I doing wrong ?
Your Model class is not managed by the container and therefore JBoss is not able to identify ejbA as an injected EJB. You have to turn your Model class into an EJB by annotating it with #Stateless/#Stateful/#Singleton.
That's why a JNDI lookup in which the container doesn't take part, works perfectly.
Suppose I want to create a service layer for my web application which uses servlets,How should I go about this?(I am not using a web app framework..So,please bear with me).Should I implement it as a listener?The service is meant to do database access.That is,I should be able to call from my servlet
class MyServlet{
...
doPost(...){
...
MyEntity entity = dbAccessService.getMyEntity(someId);
...
}
}
Where the dbAccessService should deal with hibernate session,transactions etc.Previously I used to do all this inside dao methods, but I was advised that was not a good idea.
Any suggestions welcome
thanks
mark
Sample code snippet is given below
class DBAccessServiceImpl{
...
private MyEntity getMyEntity(Long id){
Transaction tx = null;
MyEntity me = null;
Session session = HibernateUtil.getCurrentSession();
try{
tx = session.beginTransaction();
return entitydao.findEntityById(id);
}catch(RuntimeException e){
logger.info("problem occurred while calling findEntityById()");
throw e;
}
}
...
}
Then create a listener to instantiate DBAccessService
class MyAppListener implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent ctxEvent) {
ServletContext sc = ctxEvent.getServletContext();
DBAccessService dbservice = new DBAccessServiceImpl();
sc.setAttribute("dbAccessService",dbservice);
}
}
In web.xml add listener
...
<listener>
<listener-class>myapp.listeners.MyAppListener</listener-class>
</listener>
...
Assuming you do not want to introduce a framework, two options make sense (in my opinion):
define your service layer using stateless EJB session beans. You need an EJB container.
do it as always in OO languages, create an interface and a corresponding implementation:
Define an interface
public interface BusinessService {
abstract public BusinessObject performSomeOperation(SomeInput input);
}
And an implementation
public class BusinessServiceImpl implements BusinessService {
public BusinessObject performSomeOperation(SomeInput input) {
// some logic here...
}
}
You have several options for instantiating the service. If you start from scratch with a small application it may be sufficient to simply instantiate the service inside your web application:
BusinessService service = new BusinessServiceImpl();
service.performSomeOperation(...);
BTW: At a later time you may want to refactor and implement some abstractions around the Service instantiation (Factory pattern, dependency injection, etc.). Furthermore, in large systems there is a chance that you have to host the service layer on it's own infrastructure for scalability, so that your webapp communicates with the service layer via an open protocol, be it RESTful or Web Services.
However the future looks like, having a well defined interface defining your business functions in place, allows you to "easily" move forward if the application grows.
Response to your update:
I would not implement the service itself as a listener, this does not make sense. Nevertheless, your sample code seems to be reasonable, but you must distinguish between the Service (in this case DBAccessService) and the way you instantiate/retrieve it (the listener). The listener you've implemented plays in fact the role of a ServiceLocator which is capable of finding a certain services. If you store the instance of your Service in the servlet context you have to remind that the service implementation must be thread safe.
You have to be carefull to not over-engineer your design - keep it simple as long as you cannot foresee further, complex requirements. If it's not yet complex I suggest to encapsulate the implementation using a simple static factory method:
public final class ServiceFactory {
public static DBAccessService getDBAccessService() {
DBAccessService service = new DBAccessServiceImpl();
return service;
}
}
Complex alternatives are available to implement the ServiceFactory and nowadays some call it anti-pattern. But as long as you do not want to start with dependency injection (etc.) this one is still a valid solution. The service implementation DBAccessServiceImpl is accessed at one place only (the factory). As I mentioned before - keep an eye on multi-threading... hope this helps!
What you're suggesting is really no different to doing the session and transaction handling in a DAO. After all, your service class calls the DAO; to the client code, there is no difference.
Rather, i suspect that whoever told you not to put the session handling in the DAO was thinking that you should instead use Open Session In View pattern. Very simply, in its usual form, that involves writing a Filter which opens a session and starts a transaction before passing the request down the chain, and then commits the transaction (or rolls it back if necessary) and closes the session after the request completes. That means that within any one request, all access to persistent objects happens in a single transaction and a single session, which is usually the right way to do it (it's certainly the fastest way to do it).