The init method gets called again and again on every request in servlet.
Here is the code:
public class PersonInfoController extends HttpServlet {
private static final long serialVersionUID = 1L;
public PersonInfoController() {
super();
}
public void init() throws ServletException {
Connection connection = Database.getConnection();
System.out.println("init method");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<PersonInfoServiceI> myList = new ArrayList();
PersonInfoServiceI instance = new PersonInfoServiceImpl();
myList = instance.getdata();
String jsonstring = new Gson().toJson(myList);
request.setAttribute("List", jsonstring);
RequestDispatcher rd = request.getRequestDispatcher("showdata.jsp");
rd.forward(request, response);
}
public void destroy() {
System.out.println("the destory");
}
}
According to your code init() should call only once when servlet will load on first request. Then after its destruction init() will be called again on new request. In between only your service method will be called. Your code is good having no logical mistakes.
Are you calling init method outside the servlet?
Can you attach you deployment descriptor?
Related
I have simple servlet, how to check if the message has been displayed?
#WebServlet(name = "helloWorld", value = "/hello.world")
public class HelloWorld extends HttpServlet
{
private String message;
public void init()
{
message = "Hello World!";
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException
{
PrintWriter out = response.getWriter();
out.println(message);
}
}
I wrote a method which return an Array converted as String. When calling this method in the main method and printing it out the array is filled. When I am calling the same method in the doGet method for printing it in my html file, the array is empty and it prints only: []
Normally the doGet method schould work because when the method return not the array but just "hello" the html file print the String.
Here ist the code:
public static String test(senderonpremise s){
String t;
//this should be printed
t = String.valueOf(s.arrivalList);
//startSending();
//this works in doGet()
//return "this works";
// when I return this it works in the main-method but not in DoGet()
return t;
}
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/event-stream");
resp.setCharacterEncoding("UTF-8");
senderonpremise s = new senderonpremise();
PrintWriter out = resp.getWriter();
String next = "data: " + test(s) + "\n\n";
out.write(next);
out.flush();
}
/**
public static void main(String[] args) {
senderonpremise s = new senderonpremise();
System.out.print(test(s));
}
**/
I recommend you using the JEaSSE library: https://github.com/mariomac/jeasse, which is lightweight and works out of the box with Servlets 3.x
#WebServlet(asyncSupported = true)
public class ExampleServlet1 extends HttpServlet {
EventTarget target;
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
target = new ServletEventTarget(req).ok().open();
}
public void onGivenEvent(String info) {
target.send("givenEvent",info);
}
}
I am trying to replace the simple factory StatsCreatorFactory.java class in order to delete the stink multiple use of switch case statements. This is my situation:
StatsServlet.java
public class StatsServlet extends HttpServlet{
private static final long serialVersionUID = 1L;
protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
StatsContext context = new StatsContext(request,response);
**IStatsCreator creator = StatsCreatorFactory.getCreator(context);**
IChart chart = creator.createChart();
String jsonChart = creator.chartToJson(chart);
creator.sendResponse(jsonChart);
}
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
processRequest(request, response);
}
}
IStatsCreator.java
public interface IStatsCreator {
public IChart createChart() throws IOException;
public IDetailsTable createDetailsTable(String itemSelected);
public String chartToJson(IChart chart);
public String tableToJson(IDetailsTable table);
public void sendResponse(String resp) throws IOException;
public List<File> findFiles() throws IOException, ParseException;
public List<LogLine> parseFiles(List<File> files) throws IOException;
public IFileIntervalDateDetector getFileDetector() throws IOException;
public TargetChartOperation getTargetOperation();
public IChart getChart();
public IDetailsTable getDetailsTable();
}
AbstractStatsCreator
public abstract class AbstractStatsCreator implements IStatsCreator{
protected StatsContext context;
public AbstractStatsCreator(StatsContext context) {
this.context = context;
}
protected abstract ILogParser getParser();
protected abstract IStatsHelper getHelper();
#Override
public IFileIntervalDateDetector getFileDetector() throws IOException {
IFileIntervalDateDetector fileDetector = new FileDetector();
fileDetector.addPattern(new FileNamePattern(TypeSubjectEnum.valueOf(context.getSubject().toUpperCase()).getFilePattern()));
fileDetector.addPattern(new FileNamePattern(context.getInstance()));
return fileDetector;
}
#Override
public final List<File> findFiles() throws IOException, ParseException{
if(context.getDateStart().equalsIgnoreCase(StringUtils.EMPTY) && context.getDateEnd().equalsIgnoreCase(StringUtils.EMPTY)){
return getFileDetector().findDailyFiles();
}
Date startDate = new SimpleDateFormat("ddMMyyyy").parse(context.getDateStart());
Date stopDate = new SimpleDateFormat("ddMMyyyy").parse(context.getDateEnd());
Date currentDate = new Date(System.currentTimeMillis());
if(DateUtils.isSameDay(startDate, stopDate) && DateUtils.isSameDay(startDate, currentDate)){
return getFileDetector().findDailyFiles();
}
return getFileDetector().findFilesByInterval(context.getDateStart(), context.getDateEnd());
}
#Override
public final List<LogLine> parseFiles(List<File> files) throws IOException{
return getParser().parseLogFiles(files);
}
#Override
public IChart createChart() throws IOException{
if(context.needUpdate()){
List<File> files = null;
try {
files = findFiles();
} catch (ParseException e) {
files=Lists.newArrayList();
}
List<LogLine> logLines = parseFiles(files);
context.setLogLines(logLines);
context.updateContext();
}
IChart chart = getChart().create();
return chart;
}
#Override
public IDetailsTable createDetailsTable(String itemSelected) {
IDetailsTable table = getDetailsTable().create(itemSelected);
return table;
}
#Override
public String chartToJson(IChart chart) {
StringBuilder json = new StringBuilder(JsonTransformer.renderChart(chart));
return json.toString();
}
#Override
public String tableToJson(IDetailsTable table) {
StringBuilder json = new StringBuilder(JsonTransformer.renderDetailsTable(table));
return json.toString();
}
#Override
public void sendResponse(String resp) throws IOException {
context.getResponse().setContentType("application/json");
PrintWriter out = context.getResponse().getWriter();
out.write(resp.toString());
out.flush();
}
}
StatsCreatorFactory.java
public class StatsCreatorFactory {
public static IStatsCreator getCreator(StatsContext context){
if(context == null){
throw new IllegalArgumentException("Context nullo");
}
IStatsCreator creator=null;
switch (context.getOperation()) {
case "validate":
creator = new ValidateStatsCreator(context);
break;
case "extract":
creator = new ExtractStatsCreator(context);
break;
case "transform":
creator = new TransformStatsCreator(context);
break;
case "view":
creator = new ViewStatsCreator(context);
break;
default:
creator = new GeneralStatsCreator(context);
break;
}
return creator;
}
}
I would try to find a way to instantiate ICreator classes avoiding simple factory class, is there any refactoring or design pattern could I use?
Reading Martin Fawler's book I wonder if I can use polymorphism, but I can't find any way to replicate it in my code.
I would first try to modify the IStatsCreator and AbstractStatsCreator to have a stateless bean.
In your example, you have only to get rid of the StatsContext context defined as a class variable in AbstractStatsCreator. So the context should not be bound to the class instance. It should be passed in from outside when ever a method is called on the creator that needs the context. For that you can refactor your IStatsCreator and add the context to all methods that needs it.
for example:
public IChart createChart() throws IOException;
new:
public IChart createChart( StatsContext context ) throws IOException;
and so on.
After that you don't have to create new instances of AbstractStatsCreator implementations for every context call. you just need to have an instance per type. This instances of type can be mapped in the StatsCreatorFactory and just get when they needed. I would also recomend to ged rid of static methods. Make StatsCreatorFactory a real bean that can easier be managed and also easier be mocked for tests.:
public class StatsCreatorFactory {
private Map<String, IStatsCreator> statsCreators = new HashMap<String, IStatsCreator>();
public void registerStatsCreator( String type, IStatsCreator creator ) {
statsCreators.put( type, creator );
}
public IStatsCreator getCreator( String type ){
IStatsCreator creator= statsCreators.get( type );
if(creator == null){
throw new IllegalArgumentException("no creator registered for type : " + type);
}
return creator;
}
}
At the end StatsCreatorFactory is more like a provider then a factory. Maybe you can also rename it to StatsCreatorProvider.
public class StatsServlet extneds HttpServlet{
private static final long serialVersionUID = 1L;
private StatsCreatorProvider statsCreatorProvider;
public void init() {
statsCreatorProvider = new StatsCreatorProvider();
statsCreatorProvider.registerStatsCreator( "validate", new ValidateStatsCreator() );
statsCreatorProvider.registerStatsCreator( "extract" new ExtractStatsCreator() );
...
}
protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
StatsContext context = new StatsContext(request,response);
IStatsCreator creator = statsCreatorProvider.getCreator( context.getOperation() );
IChart chart = creator.createChart( context );
String jsonChart = creator.chartToJson(chart);
creator.sendResponse(jsonChart);
}
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
processRequest(request, response);
}
}
I am calling a Servlet using its URL address. This is the URL I am typing
http://localhost:7001/ryan/olympics?action=selectCatalog&id=1
This is the Servlet's URL for sure; if I change the address I get
page not found
This is the code for the Servlet.
public class Servlet extends javax.servlet.http.HttpServlet
implements javax.servlet.Servlet {
private static final long serialVersionUID = 1L;
public Servlet() {
super();
}
public void init(ServletConfig config) throws ServletException {
System.out.println("*** initializing controller servlet.");
super.init(config);
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
String action = request.getParameter("action");
if (action.equals("selectCatalog")) {
String categoryId = request.getParameter("id");
ProductModelDAO dao4 = new ProductModelDAOImpl("jpac");
if (categoryId != null && !categoryId.trim().equals("")) {
CategoryDAO dao1 = new CategoryDAOImpl("jpac");
try {
Category category = dao1.getCategoryName(categoryId);
request.setAttribute("category", category);
} catch (Exception e) {
e.printStackTrace();
}
}
try {
#SuppressWarnings("unchecked")
List<Product> products = dao4
.getProductsByCategory(categoryId);
request.setAttribute("products", products);
} catch (Exception e) {
e.printStackTrace();
}
url = "SelectCatalog.jsp";
RequestDispatcher requestDispatcher =
getServletContext().getRequestDispatcher(url);
requestDispatcher.forward(request, response);
I get the NullPointerException pointing to the RequestDispatcher's line. Any help?
Try changing "SelectCatalog.jsp" to "/SelectCatalog.jsp", because, as I understand, You want to use an absolute path.
If you want to use a relative path you have to use:
request.getRequestDispatcher(url);
in place of:
getServletContext().getRequestDispatcher(url);
request.getParameter("action");
code is written in doPost method. Are you invoking this servlet from doPost method of calling servlet? URL parameters will not be used by doPost method.
I'm trying to tracking valid user Ids in my Java servlet, can I implement HttpSessionListener this way ?
public class my_Servlet extends HttpServlet implements HttpSessionListener
{
String User_Id;
static Vector<String> Valid_User_Id_Vector=new Vector<String>();
private static int activeSessions=0;
public void sessionCreated(HttpSessionEvent se)
{
// associate User_Id with session Id;
// add User_Id to Valid_User_Id_Vector
Out(" sessionCreated : "+se.getSession().getId());
activeSessions++;
}
public void sessionDestroyed(HttpSessionEvent se)
{
if (activeSessions>0)
{
// remove User_Id from Valid_User_Id_Vector by identifing it's session Id
Out(" sessionDestroyed : "+se.getSession().getId());
activeSessions--;
}
}
public static int getActiveSessions()
{
return activeSessions;
}
public void init(ServletConfig config) throws ServletException
{
}
public void destroy()
{
}
protected void processRequest(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException
{
User_Id=request.getParameter("User_Id");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
processRequest(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
processRequest(request, response);
}
public String getServletInfo()
{
return "Short description";
}
}
How to get the listener notified when a session ends ? I'm trying to bypass "/WEB-INF.web.xml" all together, is it doable ? Or does it make sense ?
This won't bypass /WEB-INF/web.xml. Furthermore, you'll end up with 2 instances of this class, not 1 performing both functions. I suggest you put this Vector in the ServletContext and have 2 separate classes.
In the servlet, you get to it via getServletContext(). In the listener, you'll do something like this:
public void sessionCreated(HttpSessionEvent se) {
Vector ids = (Vector) se.getSession().getServletContext().getAttribute("currentUserIds");
//manipulate ids
}