Changing an EJB from 2.1 to 3.0 - java

I have an existing Web Application (Servlet) that remotely accesses an EJB currently written to the EJB 2.1 Specification (EJBHome, EJBObject, SessionBean, all configuration in ejb-jar.xml). The servlet access the EJB via JNDI lookup, the JNDI name being specified in weblogic-ejb-jar.xml.
I would like to update the EJB to EJB3.0, which will (hopefully) make it easier to add to the API.
My issue is that I need to do it with a minimum of change to the existing servlet code. In other words, I still need to:
Access the EJB with a simple, global JNDI name (it is stored in a database, and the servlet can can change the name it looks up on the fly), and
Be able to use the 2.1 style:
String jndiName = getJndiName(); // e.g. "BeanV2.0"
BeanHome home = (BeanHome) PortableRemoteObject.narrow(
jndiContext.lookup(jndiName), BeanHome.class);
BeanRemote remote = home.create();
remote.doBusiness(); // call business method
I have tried a stripped down version, applying #RemoteHome, but I keep getting errors during deployment.
I am deploying (for development/production) on Weblogic, mostly 10.3.5 (11gR1), and am limited to EJB 3.0. I am using Eclipse (with the Oracle Weblogic Pack) for development.
Thanks.

I would suggest you to first understand the architectural difference between EJB2.1 and EJB3.x (refer here)
You will have some major/minor changes in code based on your bean implementation and client side invocation, because of the removal of Home and Deployment Descriptor in EJB3.x
Refer this example for accessing EJB3.x from a client, in your case Servlet
/**
* Servlet implementation class SampleServlet
*/
public class SampleServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public SampleServlet() {
super();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
Context ctx=getInitialContext();
String jndiName=getJndiName(); // eg. java:global/BeanProject/Bean!demo.BeanRemote
BeanRemote beanRemote = (BeanRemote)ctx.lookup(jndiName);
remote.doBusiness();
} catch(Exception exception) {
System.out.println(exception.getMessage());
}
}
private static Context getInitialContext() throws Exception
{
Properties properties=new Properties();
properties.put("java.naming.factory.initial","org.jboss.naming.remote.client.InitialContextFactory");
properties.put("java.naming.provider.url","remote://localhost:4447");
return new InitialContext(properties);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
Hope this helps!

Related

Dynamic URL routes with java EE

I'm super new to java web application development. Working on basic Todos app. So far app is working fine. I wish to add dynamic url routes like updateTodos, deleteTodos to existing path.
Expected behavior as shown below
/todos
*render todos list*
/todos/update
*render updateTodos.jsp*
/todos/delete
*render deleteTodos.jsp*
Below is my code
#WebServlet(urlPatterns = "/todos")
public class UserTodos extends HttpServlet {
private TodoService todoService = new TodoService();
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
if(request.isRequestedSessionIdValid()){
request.setAttribute("userName", request.getParameter("userName"));
request.setAttribute("allTodos", todoService.retrieveTodos());
request.getRequestDispatcher("WEB-INF/views/todos.jsp").forward(request, response);
}else{
response.sendRedirect("/login");
}
}
}
My understanding is so far that the annotation #WebServlet triggers the class file based on route defined. Can I achieve the above with a single class file?
Something like being done in JS web-framework Express-JS
If I sum-up my whole query is - Is it possible to multiple doGet and doPost methods in a single class file which will be executed based on user's URL accessed?
Update
I was able to achieve this, not sure whether this is correct implementation or not :/

How to inject a ServletContext outside of CDI lifecycle

I need access to the ServletContext to use the getRealPath() method on some files that are in my WEB-INF directory. However, the class I need to do this work in is a non-CDI class that is used for some backend processing based on a request made earlier from JAX-RS. How can I get the ServletContext outside of the lifecycle of the JAX-RS request?
I'm using Wildfly 10, if that changes the way I would go about this
The trick is to load a servlet at the startup of the Java EE application, see #WebServlet annotation. The Servlet.init() method is invoked upon startup of the container, which we will leverage to work with ServletContext, in this case calling getRealPath() and storing returned value into static variable. You may access the value from the rest of your app by calling RealPathServlet.getRealPath().
#WebServlet(value="/real-path", loadOnStartup=1)
public class RealPathServlet extends HttpServlet {
private static String realPath;
public void init(ServletConfig config) throws ServletException {
super.init(config);
realPath = config.getServletContext().getRealPath("yolo");
Logger.getLogger(ContextPathServlet.class.getName()).info("Real path is " + realPath);
}
public static getRealPath() {
return realPath;
}
...
}

Share Session between liferay portlet and servlet

I'm trying to share a session between a liferay portlet and a servlet, running in the same WAR.
I'm setting the attribute like this in the LoginPostAction (Hook):
#Override
public void run(HttpServletRequest request, HttpServletResponse response) throws ActionException {
Gebruiker g = new Gebruiker();
request.getSession().setAttribute("gebruiker", gebruiker);
}
Trying to get this Gebruiker object in my servlet, through an AJAX-request:
#RequestMapping(value="/haalContactGegevens", method = RequestMethod.POST)
public #ResponseBody ContactGegevensMessage getContactGegevens(HttpServletRequest request, HttpServletResponse response) {
Gebruiker gebruiker = (Gebruiker)request.getSession(true).getAttribute("gebruiker");
}
But here my 'Gebruiker-object' stays null.
What am I doing wrong?
thx
Easy: The LoginPostAction is handled by Liferay (even though technically implemented in your webapp's context/classloader. However, if you look at the httpServletRequest's context path, it's Liferay's.
When you implement a servlet in your own webapp, it will have its own session, unrelated to Liferay's.
You should rather implement a portlet and utilize its serveResource lifecycle method to handle the Ajax request - this will make you part of the whole portal environment. However, you should also minimize use of the Http-level session: It's prone to become a source for memory leaks sooner or later.
Note: While implementing a portlet will give you access to the HttpServletRequest (through PortalUtil), this is discouraged for the reasons given above. But as I don't know what you're trying to achieve, this would be part of the quickfix for the code that you give in your question.

How do i perform Gravity data push from HttpServlet

Last few days i was playing with GranideDS tutorials (using Spring server and AIR client)
https://github.com/graniteds-tutorials/graniteds-tutorial-data
"This tutorial shows how to build a simple data application that
manages a database of user accounts. All connected clients are
notified and synchronized with data updates using a GraniteDS long
polling channel."
Unfortunately i cannot find any GraniteDS javascript client library or example.
I created an HttpServlet to manage (add Entity for example) persistense context using http (ajax) requests.
my TestServlet.java
#WebServlet("/TestServlet")
public class TestServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(this.getServletContext());
AccountService srvObject = (AccountService) wac.getBean("testService");
//testService mean spring service annotation parameter
Account emp = new Account();
emp.setName(request.getParameter("name"));
emp.setEmail(request.getParameter("email"));
srvObject.save(emp);
response.getWriter().println("OK");
}
}
This method adds an entity correctly but connected client's data are NOT syncronized. How can i notify all clients about new changes?
UPDATE:
I was trying to change DataEnabled's publish to PublishMode.ON_COMMIT
#DataEnabled(topic="dataTopic", publish=DataEnabled.PublishMode.ON_COMMIT, useInterceptor=true)
add to application-context.xml
<graniteds:tide-data-publishing-advice/>
In this case both air application and servlet causing server error:
SEVERE: Could not register synchronization for ON_COMMIT publish mode,
check that the Spring PlatformTransactionManager supports it and that
the order of the TransactionInterceptor is lower than the order of
TideDataPublishingInterceptor
And <graniteds:tide-data-publishing-advice order="-1"/> does not helps.
You can try the mode ON_SUCCESS with useInterceptor=true
"useInterceptor=true" is necessary because it's what will make GraniteDS aware of your service which is called completely outside its control

Servlets with Database design

I have a general question about using Servlet and JDBC.
For instance, I have a class called MyDatabaseManager, which provides functions
public boolean updateUser(User user) {...}
public boolean deleteUser(User user) {...}
public boolean inserUser(User user){...}
, these functions will access and manipulate the Database.
My question is on the Servlet implementation. I am using three Servlets (UpdateUserServlet,InsertUserServlet and DeleteUserServlet) at the moment and each Servlet calls the MyDatabaseManager instance (only one instance here, using Singleton pattern) function. (For example, UpdateUserServlet calls MyDatabaseManager.updateUser ...).
I think this is the most straightforward way of using Servlet and Database. But I am not sure if this is the correct way of doing it. For example, how is this implemented in the industry world.
People don't really use servlets directly nowadays, they use frameworks that allow you to simplify your work, but if you really want to use servlets, you can make all actions in a single one, using the other methods, doPut, doDelete and even creating your own methods. Here's a sample of how you would do it:
public abstract class BaseServlet extends HttpServlet {
#Override
protected void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
String method = request.getParameter("_method");
if ("form".equals(method)) {
this.doForm(request, response);
} else {
if ("delete".equals(method)) {
this.doDelete(request, response);
} else {
super.service(request, response);
}
}
}
protected void doForm(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
throw new UnsupportedOperationException();
}
}
As you can see, this Servlet uses a special field _method on forms to decide what special method to call, if the _method is not available it's going to use the usual service method and is going to call doGet or doPost.
And here's how an implementation for this servlet would look like:
public class UsersServlet extends BaseServlet {
private UsersRepository cadastro = new UsersRepository();
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.setAttribute("usuarios", cadastro.list());
req.getRequestDispatcher("/usuarios/listar.jsp").forward(req, resp);
}
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
User usuario = this.getUser(req);
usuario.setNome(req.getParameter("nome"));
usuario.setEmail(req.getParameter("email"));
usuario.setSenha(req.getParameter("senha"));
this.cadastro.persist(usuario);
resp.sendRedirect(req.getContextPath() + "/usuarios");
}
protected User getUser(HttpServletRequest req) {
User usuario;
if (req.getParameter("id") == null) {
usuario = new Usuario();
} else {
Long id = new Long(req.getParameter("id"));
usuario = this.cadastro.search(id);
}
return usuario;
}
#Override
protected void doDelete(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
User usuario = this.getUser(req);
this.cadastro.remover(usuario);
resp.sendRedirect(req.getContextPath() + "/usuarios");
}
#Override
protected void doForm(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
User usuario = this.getUser(request);
request.setAttribute("usuario", usuario);
request.getRequestDispatcher("/usuarios/form.jsp").forward(request,
response);
}
}
This way you can make it all in a single servlet.
Difficult to answer because there are hundreds of design patterns out there! I know a good one about Database management is called DAO (data access objects). I use this one a lot. I advice you to take a look.
Don't get me wrong, a Singleton to hold your Manager is a good idea. Pretty much that's what I usually do too. However, usually I have a DAOFactorySingleton which pretty much have the responsibility to generate all classes DAO in my app and this factory is good because I can have some DataSource rules that this factory just poll from somewhere and inject in my DAO! So, pretty much, each DAO doesn't have to care about things like JDBC connection!
Follow 2 links to explain more about DAO!
http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html
http://community.jboss.org/wiki/GenericDataAccessObjects
The second one is to use with hibernate! you can read it and is not mandatory using just with hibernate. I really like that second one, more complex though.
This is surely a matter of design choice, you can adopt a framework like Spring, Struts etc.. which make this much easier. Alternatively if you want to use the classic servlet request/response pattern, I will suggest creating a parent servlet which intercepts request and passes it on to the right method to perform the request.
Additionally you have a choice to various ORM solutions like Hibernate, JPA etc.. which you can use to handle your database access operations. Yet if you choose to stick to the classic JDBC calls, you can use Filters and Handlers to decide which calls to provide wrap database connection and operation against.
Singleton on the Database class sounds good, especially as it seems to contain update/delete/insert code.
If you're using Connection Pools, make sure you Singleton the DataSourceFactory.
Many in the industry use ORM + Dependency Injection framework + transaction manager + database pooling libraries, for example Hibernate (ORM) + Spring DI (Dependency Injection) + Spring transaction manager (transaction manager) + Apache DBCP (DB connection pooling).
Sometimes when the use of ORM cannot be justified (e.g. very simple DB schema, ORM performance overhead is prohibitive due to the nature of the app. etc.), developers might use raw JDBC. Many would still use dependency injection and DB connection pooling.
It is very rare that the use of dependency injection or DB connection pooling cannot be justified. I.e., unless it is a very rare, special app., developers in the industry do use dependency injection framework and DB connection pooling.
In this case the state that needs to be managed is managed by the DB connection pooling framework, so you should not have to worry about state management or thread safety (as long as you don't share anything between different threads yourself and follow the API of the DB connection pool framework). I.e., you won't need a singleton. If you implement your own DB connection pool, then using a singleton would make sense.
If a developer doesn't want to use any framework (e.g. creating a very simple tool), then many would just open a connection every time (for each thread). In this case, you again don't need to manage any state so you won't need a singleton.
In the industry world, we are all for simplicity. For example, for user interaction from browser, to server, to a persistence storage (database), we follow these approaches.
An MVC pattern, first and foremost. This would allow us to totally not write a Servlet for each user interaction from browser to server. What this allows us to do is to do the following:
Allow the controller to handle user request and link it to our user action (our model). This model allows us to write business logic to respond to user data.
In today's Java World, Frameworks exists that meets our MVC requirements. The one that comes out the Java box is JSF (JavaServer Faces).
For backend, we definitely use databases, but we are clever too and use ORM (Object Relational Mapping) to model our real-world problem into an Object model and how to best persist (store) these object models. Some usesERM (Entity-Relational Modelling) to design a semantic data model.
In the middle, the business logic, we add a service (as the business logic layer) doesn't want to care about where to read/write data, as long as they can see the data it wants. For this, a Service layer is added that facilitates this. In essence we have this effect.
public class ActionServlet extends HttpServlet {
//Action registration
public void init() {
ActionMapping mapping = .....; //some instatiation
mapping.setAction("/userRegistration", UserRegistrationAction.class);
//Save it in Application Scope
getServletContext().setAttribute("actionConfig", mapping);
}
private void doAction(HttpServletRequest request, HttpServletResponse response) throws Exception {
String path = request.getPathInfo();
Action action = ((ActionMapping)getServletContext().getAttribute("actionConfig")).getAction(path);
if (action == null) {
throw new Exception("No action of '" + path + "' found.");
}
action.execute(request, response);
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws Exception {
doAction(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws Exception {
doAction(request, response);
}
}
public abstract class Action {
public abstract void execute(HttpServletRequest request, HttpServletResponse response) throws Exception;
protected void dispatch(HttpServletRequest request, String path) {
RequestDispatcher dispatcher = request.getRequestDispatcher(path);
dispatcher.forward(request, response);
}
}
public class UserRegistrationAction extends Action {
public void execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
//Business Logic goes here...
//Call DAO,
UserRegistrationDAO dao = ; //Some DAO instantation
User user = createUserFromForm(request);
dao.save(user);
dispatch(request, "success");
}
}
As for persistence, Java 5 & higher comes with JPA. You can use any form of ORM that you want, depending on your project scope. There's Hibernate (which also supports JPA) or if you want to, write your own DAO.
One more thing, all these processes are tedious to glue together. Fortunately, we have frameworks that helps us make our beautiful example above much easier. Frameworks like JBoss Seam does this and it fully uses Java specifications. For now, go for the simple design models and MVC (for learning purposes). As you get accustomed to the architecture, use frameworks.

Categories

Resources