Getting the same output for Stateless and stateful session bean - ejb

Here is the sample code i tried
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Sample1</title>
</head>
<body>
<form action="ActionServlet" method="post">
<h1>This is inside sample1</h1>
<input type="submit">
</form>
</body>
</html>
posted Monday, November 19, 2012 10:58:11 PM private message
Quote
Here is the sample code that i tried
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Sample1</title>
</head>
<body>
<form action="ActionServlet" method="post">
<h1>This is inside sample1</h1>
<input type="submit">
</form>
</body>
</html>
on Clicking submit, control navigates to servlet named ActionServlet
public class ActionServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* Default constructor.
*/
public ActionServlet() {
// TODO Auto-generated constructor stub
}
/**
* #see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doPost(request, response);
}
/**
* #see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
System.out.println("This is inside doPost method for action servlet");
System.out.println("Before calling EJB for action servlet");
try{
Context ic = new InitialContext();
//first instance creation
StateFulServiceHome home=(StateFulServiceHome)ic.lookup("Stateful1234");
StateFulService sample=(StateFulService)home.create();
sample.setName("Hello1223");
sample.getName();
//second instance creation
Context ic1 = new InitialContext();
StateFulServiceHome home1=(StateFulServiceHome)ic1.lookup("Stateful1234");
StateFulService sample1=(StateFulService)home1.create();
sample1.getName();
}catch (Exception e) {
e.printStackTrace();
}
System.out.println("After calling EJB in action servlet1");
request.getRequestDispatcher("Sample2.jsp").forward(request,response);
}
}
ActionServlet calls business method on a bean named stateful session bean
public class StateFulBean implements SessionBean{
String name;
public void setName(String name)throws RemoteException{
this.name =name;
}
private SessionContext context;
public void ejbActivate() throws EJBException, RemoteException {
// TODO Auto-generated method stub
System.out.println("*********This is inside ejbActivate method***********");
}
public void ejbPassivate() throws EJBException, RemoteException {
// TODO Auto-generated method stub
System.out.println("*********This is inside ejbpassivate method***********");
}
public void ejbRemove() throws EJBException, RemoteException {
// TODO Auto-generated method stub
System.out.println("*********This is inside Ejb remove method***********");
}
public void ejbCreate() throws EJBException,RemoteException{
System.out.println("*********This is inside create method***********");
}
public void setSessionContext(SessionContext ctx) throws EJBException,
RemoteException {
// TODO Auto-generated method stub
context=ctx;
System.out.println("*********This is for set session context***********");
}
public void getName()throws RemoteException{
System.out.println("***********This is for start of getting business method*****");
System.out.println("The name obtained is"+this.name);
System.out.println("***********This is for end of getting business method*****");
}
}
public interface StateFulService extends EJBObject {
public void getName()throws RemoteException;
public void setName(String name)throws RemoteException;
}
public interface StateFulServiceHome extends EJBHome {
public StateFulService create() throws RemoteException,CreateException;
}
and finally my ejb-jar.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN" "http://java.sun.com/dtd/ejb-jar_2_0.dtd">
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>Stateful1234</ejb-name>
<home>StateFulServiceHome</home>
<remote>StateFulService</remote>
<ejb-class>StateFulBean</ejb-class>
<session-type>Stateful</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
</ejb-jar>
I am getting the same output for stateful and stateless session bean, My assumption is when my bean is defined as stateful, I should get the name during lookup of bean for the second time.
Let me know if I am wrong somewhere.
-Shyam

My assumption is when my bean is defined as stateful, I should get the name during lookup of bean for the second time.
That's not how stateful session beans work. When you use a stateful session bean, you can store the proxy to the bean "somewhere" i.e. so that the container will passivate it when you do not invoke methods on it for a certain period. The container would "remember" the client (the servlet in your case), should a subsequent request be made through the proxy at any time before the bean is destroyed. In other words, subsequent invocations will remember the conversational state, and hence the stateful nature of the session bean. You can store state in the session bean, even across HTTP requests (hence, the reason for storing the reference to the proxy).
Note that this has very little to do with lookups. In your code:
//first instance creation
StateFulServiceHome home=(StateFulServiceHome)ic.lookup("Stateful1234");
StateFulService sample=(StateFulService)home.create();
sample.setName("Hello1223");
sample.getName();
//second instance creation
Context ic1 = new InitialContext();
StateFulServiceHome home1=(StateFulServiceHome)ic1.lookup("Stateful1234");
StateFulService sample1=(StateFulService)home1.create();
sample1.getName();
you've created two instances of the session bean and you have two proxies to them. The second bean is obviously not going to know of the state stored in the first.
To consider stateless session beans, then you'll need to remember that it is a bit pointless to store references to their proxies, especially in a HttpSession object. This is primarily because state stored within the bean is valid only for the duration of the method invocation. The EJB container manages a pool of stateless session beans, and each invocation may involve a different unused instance in the pool.
PS - Is there any reason why you're learning EJB 2.x now ? Not only is it old, parts of it are no longer required in Java EE 6 apps, and some portions (entity beans) are being pruned in Java EE 7.

Related

exception handling for rabbitmq listener in spring

Working with spring, I am new to rabbitmq, i want to know where i am wrong.
I have written a rabbitmq connection factory, and a listener container containing a listener. I have also provided the listener container with an error handler but it doesnt seems to work.
My spring beans:
<rabbit:connection-factory id="RabbitMQConnectionFactory" virtual-host="${rabbitmq.vhost}" host="${rabbitmq.host}" port="${rabbitmq.port}" username="${rabbitmq.username}" password="${rabbitmq.password}"/>
<rabbit:listener-container missing-queues-fatal="false" declaration-retries="0" error-handler="errorHandlinginRabbitMQ" recovery-interval="10000" auto-startup="${rabbitmq.apc.autostartup}" max-concurrency="1" prefetch="1" concurrency="1" connection-factory="RabbitMQConnectionFactory" acknowledge="manual">
<rabbit:listener ref="apcRabbitMQListener" queue-names="${queue.tpg.rabbitmq.destination.apc}" exclusive="true" />
</rabbit:listener-container>
<bean id="errorHandlinginRabbitMQ" class="RabbitMQErrorHandler"/>
This is my RabbitMQErrorHandler class:
public class RabbitMQErrorHandler implements ErrorHandler
{
#Override
public void handleError(final Throwable exception)
{
System.out.println("error occurred in message listener and handled in error handler" + exception.toString());
}
}
What i assume is, if i provide invalid credentials to the connection factory, handleError method of the RabbitMQErrorHandler class should execute, and the server should start properly, however, when i try to run the server, the method does not executes(the exception is thrown in console) and the server is not able to start. Where am i missing something and what that might be?
The error handler is for handling errors during message delivery; since you haven't connected yet, there is no message for which to handle an error.
To get connection exceptions, you should implement ApplicationListener<ListenerContainerConsumerFailedEvent> and you will receive the failure as an event if you add it as a bean to the application context.
You will get other events (consumer started, consumer stopped etc) if you implement ApplicationListener<AmqpEvent>.
EDIT
<rabbit:listener-container auto-startup="false">
<rabbit:listener id="fooContainer" ref="foo" method="handleMessage"
queue-names="si.test.queue" />
</rabbit:listener-container>
<bean id="foo" class="com.example.Foo" />
Foo:
public class Foo {
public final CountDownLatch latch = new CountDownLatch(1);
public void handleMessage(String foo) {
System.out.println(foo);
this.latch.countDown();
}
}
App:
#SpringBootApplication
#ImportResource("context.xml")
public class So43208940Application implements CommandLineRunner {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(So43208940Application.class, args);
context.close();
}
#Autowired
private SimpleMessageListenerContainer fooContainer;
#Autowired
private CachingConnectionFactory connectionFactory;
#Autowired
private RabbitTemplate template;
#Autowired
private Foo foo;
#Override
public void run(String... args) throws Exception {
this.connectionFactory.setUsername("junk");
try {
this.fooContainer.start();
}
catch (Exception e) {
e.printStackTrace();
}
Thread.sleep(5000);
this.connectionFactory.setUsername("guest");
this.fooContainer.start();
System.out.println("Container started");
this.template.convertAndSend("si.test.queue", "foo");
foo.latch.await(10, TimeUnit.SECONDS);
}
}

Weld ContextNotActiveException in async servlet

Environment:
WildFly 9.0.1/9.0.2
Java EE 7 Full profile
Weld CDI environment.
Because of the number of requests I am expecting, I want to implement async request on top of the FacesServlet, and did this:
public class AsyncFacesServlet extends HttpServlet {
private static final long serialVersionUID = 111966573758921845L;
private FacesServlet delegate;
#Inject
private BeanManager beanManager;
#Inject
private ServletContext servletContext;
#Override
public void init(final ServletConfig servletConfig) throws ServletException {
delegate = new FacesServlet();
delegate.init(servletConfig);
}
#Override
public void destroy() {
delegate.destroy();
}
#Override
public ServletConfig getServletConfig() {
return delegate.getServletConfig();
}
#Override
public String getServletInfo() {
return delegate.getServletInfo();
}
#Override
public void service(final ServletRequest request, final ServletResponse response) throws ServletException, IOException {
final AsyncContext asyncContext = request.isAsyncStarted()
? request.getAsyncContext() : request.startAsync(request, response);
final Runnable runnable = () -> {
try {
delegate.service(request, response);
} catch (final IOException | ServletException ex) {
throw Throwables.propagate(ex);
}
};
asyncContext.start(runnable);
}
}
And then updated my web.xml as:
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>com.mycompany.service.faces.AsyncFacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
When I deploy, I get the following exceptions, which indicates that Weld was not correctly initialized inside the asynccontext.
SEVERE [javax.enterprise.resource.webcontainer.jsf.application] (default task-38) Error Rendering View[/login.xhtml]: org.jboss.weld.context.ContextNotActiveException: WELD-001303: No active contexts for scope type javax.enterprise.context.RequestScoped
at org.jboss.weld.manager.BeanManagerImpl.getContext(BeanManagerImpl.java:708)
at org.jboss.weld.bean.ContextualInstanceStrategy$DefaultContextualInstanceStrategy.get(ContextualInstanceStrategy.java:95)
at org.jboss.weld.bean.ContextualInstanceStrategy$CachingContextualInstanceStrategy.get(ContextualInstanceStrategy.java:178)
at org.jboss.weld.bean.ContextualInstance.get(ContextualInstance.java:50)
at org.jboss.weld.manager.BeanManagerImpl.getReference(BeanManagerImpl.java:761)
at org.jboss.weld.el.AbstractWeldELResolver.lookup(AbstractWeldELResolver.java:107)
at org.jboss.weld.el.AbstractWeldELResolver.getValue(AbstractWeldELResolver.java:90)
at org.jboss.as.jsf.injection.weld.ForwardingELResolver.getValue(ForwardingELResolver.java:46)
at javax.el.CompositeELResolver.getValue(CompositeELResolver.java:188)
at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:176)
at com.sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.java:203)
at com.sun.el.parser.AstIdentifier.getValue(AstIdentifier.java:116)
at com.sun.el.parser.AstValue.getBase(AstValue.java:151)
at com.sun.el.parser.AstValue.getValue(AstValue.java:200)
at com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:226)
at org.jboss.weld.el.WeldValueExpression.getValue(WeldValueExpression.java:50)
at org.jboss.weld.el.WeldValueExpression.getValue(WeldValueExpression.java:50)
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:109)
at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:194)
at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:182)
at javax.faces.component.UIOutput.getValue(UIOutput.java:174)
at javax.faces.component.UIInput.getValue(UIInput.java:291)
at com.sun.faces.renderkit.html_basic.HtmlBasicInputRenderer.getValue(HtmlBasicInputRenderer.java:205)
at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.getCurrentValue(HtmlBasicRenderer.java:355)
at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeEnd(HtmlBasicRenderer.java:164)
at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:920)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1863)
at javax.faces.render.Renderer.encodeChildren(Renderer.java:176)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:890)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1856)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1859)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1859)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:458)
at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:134)
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337)
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337)
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:120)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:219)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:659)
at com.mycompany.service.faces.servlet.AsyncFacesServlet.lambda$service$17(AsyncFacesServlet.java:61)
Whats happening is that, Weld is not properly initialized or context is not propagated to the async context execution.
How can I be able to propagate or recreate the weld context upon async-request call?
I'll prefix my answer with a note that there is an open CDI spec issue to make async behavior more portable, Specify that web scoped (request, session, application) beans are injectable in async servlets
What you can do, in a Weld specific way, is start the context. Apache DeltaSpike has some utilities that will make this container in-specific as well, http://deltaspike.apache.org/documentation/container-control.html#ContextControlUsage
If your runnable is a managed bean, you can use BoundRequestContext in weld to start a request context for that thread. More here. The downside is that its a new context, not a bridged context.

How do I implement the business logic of a MVC in a seperate class from the Servlet?

I have experimented putting the class in the servlets controller but I have trouble with the constructor and setting method access. I read its improves efficiency to have the business logic seperate, I even tried putting it in the JavaBean but I don't yet know how to send parameters from the controller to it. I still mave much to learn, just working on a project.
You can use EJB to separate business logic from Presentation tier i.e (Servlets and JSP) in JavaEE platform. If your project doesn't have much business logic code then simply use Java POJO classes. This example gives very raw idea. you can use web frameworks which have built in MVC design.
Controller:
Use Servlets to control navigation or perform other tasks against HTTP requests.
#WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public LoginServlet() {
super();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
LoginManager loginManager=new LoginManager();
if(loginManager.isValidUser("getUserID from request Params","password from request params")){
//initialize user session and redirect to dashboard
//response.sendRedirect("/userhome.jsp");
}else{
//display failure messages. etc...
//response.sendRedirect("/login.jsp");
}
}
}
Model:
POJO which contains set of methods for login related operations.
public class LoginManager {
private Connection con;
public LoginManager() {
}
private void initConnection(){
//register driver class and create a new connection
//you can create separate DBUtils class to get new connections
//to prevent boilerplate code.
//make new connection to database
// con=..
}
private void closeConnection() throws SQLException{
con.close();
}
public boolean isValidUser(String user,String password) throws SQLException{
initConnection();
PreparedStatement pstm=con.prepareStatement("select 1 from users where userID = ? and password=?");
//set userID and password params
ResultSet rs=pstm.executeQuery();
if (rs.next()){
if(checkpassword.....)
return true;
}
closeConnection();
return false;
}
}
View:
pages like login.jsp and userhome.jsp pages are views;

Servlet initialization in a container

How does a web container know that a particular servlet hasn't been initialized. Is there any particular flag which shows the status of the servlet or anything else managed by the servlet
Container initial servlet during start up ( or restart ) one by one as mentioned in web.xml. You can also find if a servelt is initiated or destroyed by override init and destroy methods.
public class PrecompressedResourceServlet extends HttpServlet {
private static final Logger LOG = LoggerFactory
.getLogger(PrecompressedResourceServlet.class);
#Override
public void init() throws ServletException {
LOG.info("The PrecompressedResourceServlet initialized...");
super.init();
}
}

Spring beans property binding error

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'workingTimeController' defined in ServletContext resource [/WEB-INF/tracker-servlet.xml]: Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: Validator [de.intec.tracker.controller.WorkingTimeController#4610fa] does not support command class [de.intec.tracker.dto.WorkingTimeDTO]
The Working Controller is the controller classs in java
Your can define like below code snippet
LoginFormCommand
com.aims.commands.LoginFormCommand
and validator should using validator interface like below code snippet
public class LoginFormValidator implements Validator {
public boolean supports(Class arg0) {
// TODO Auto-generated method stub
return LoginFormCommand.class.equals(arg0);
}
public void validate(Object obj, Errors errors) {
// TODO Auto-generated method stub
LoginFormCommand login = (LoginFormCommand) obj;
System.out.println("validate==============");
ValidationUtils.rejectIfEmpty(errors,"username","field.required", "Required field");
ValidationUtils.rejectIfEmpty(errors,"password","field.required", "Required field");
}
}

Resources