Не должен ли метод, который получает java.lang.Object в качестве входных данных, также получать javax.servlet.jsp.JspWriter в качестве входных данных? - PullRequest
1 голос
/ 03 октября 2010

Я хотел объединить две функции .

Получив жизнеспособное решение, я решил немного поиграть с кодом и придумал следующее:

package hu.flux.helper;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import javax.servlet.jsp.JspWriter;
import com.objectmentor.library.web.framework.mocks.*;


// A holder for formatting data 
public class NameAndAddress 
{
    public String firstName;
    public String middleName;
    public String lastName;
    public String address1;
    public String address2;
    public String city;
    public String state;
    public String zip;

    public String FormattedString()
    {
        String formattedString = "\n" + firstName;

        // Add the middle name only if it contains data.
        if ((middleName != null) && (middleName.length() > 0)) 
            {formattedString += " " + middleName;}

        formattedString += " " + lastName + "\n";

        formattedString += address1  + "\n";

        if ((address2 != null) && (address2.length() > 0))
            formattedString += address2 + "\n";

        formattedString += city + ", " + state + " " + zip + "\n
"; вернуть formattedString; } // Распечатать имя и адрес. общественная пустая печать (писатель писатель) { long now = System.currentTimeMillis (); System.out.println ("- Ввод--" + сейчас); PrintWriter p = новый PrintWriter (писатель); p.write (this.FormattedString ()); now = System.currentTimeMillis (); System.out.println ("- Exiting--" + сейчас); } / * общедоступная пустая печать (JspWriter вне) бросает java.io.IOException {print (new PrintWriter (out)); } * / @SuppressWarnings ( "устаревание") public static void main (строковые аргументы []) { NameAndAddress naa = new NameAndAddress (); naa.firstName = "Брайан"; naa.middleName = "Мэтью"; naa.lastName = "Кесслер"; naa.address1 = "Tatra u. 15 / b V / 3"; naa.city = "Будапешт"; naa.state = "Венгрия"; naa.zip = "HU-1136"; System.out.println ("\ nTesting PrintWriter ..."); PrintWriter p = null; try {p = new PrintWriter ("d: /temp/pwriter_text.txt"); } поймать (FileNotFoundException e) { System.err.print («Не удается создать новый PrintWriter:» + e); e.printStackTrace (); } naa.print (р); p.flush (); FileInputStream fis; DataInputStream dis; пытаться { fis = new FileInputStream ("d: /temp/pwriter_text.txt"); dis = new DataInputStream (fis); while (dis.available ()! = 0) {System.out.println (dis.readLine ()); } dis.close (); } поймать (исключение е) { System.err.println («Ошибка ввода файла»); } System.out.println ("\ nTested PrintWriter ..."); System.out.println ( "---------------------"); System.out.println ("\ nTesting JSPWriter ..."); JspWriter j = null; naa.print (J); System.out.print ("\ nTested JSPWriter ..."); System.out.println ( "---------------------"); System.out.println ("\ nTesting MockJspWriter"); MockJspWriter m = null; m = новый MockJspWriter (255, правда); naa.print (м); System.out.print (m.getContent ()); System.out.println ("\ nTested MockJSPWriter ..."); System.out.println ( "---------------------"); } }

Я ожидал, что метод print () будет перехватывать и JspWriter, и PrintWriter.

Хотя это решение работало нормально для PrintWriter, когда я попытался запустить его как консольное приложение, я получил такой вывод:

Testing PrintWriter...
--Entering-- 
--Exiting-- 

Brian Matthew Kessler
Tatra u. 15/b V/3
Budapest, Hungary HU-1136
Протестировано PrintWriter ... --------------------- Тестирование JSPWriter ... --Entering-- Исключение в потоке "main" java.lang.NullPointerException на hu.flux.helper.NameAndAddress.print (NameAndAddress.java:46) в hu.flux.helper.NameAndAddress.main (NameAndAddress.java:101)

Однако я получаю другую ошибку, если пытаюсь получить доступ к печати (Writer Writer) из JSP:

HTTP Status 500 -

type Exception report

message

description The server encountered an internal error () that prevented it from fulfilling this request.

exception

org.apache.jasper.JasperException: javax.servlet.ServletException: java.lang.NoSuchMethodError: hu.flux.helper.NameAndAddress.print(Ljavax/servlet/jsp/JspWriter;)V
    org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:492)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:407)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:320)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:265)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
root cause

javax.servlet.ServletException: java.lang.NoSuchMethodError: hu.flux.helper.NameAndAddress.print(Ljavax/servlet/jsp/JspWriter;)V
    org.apache.jasper.runtime.PageContextImpl.doHandlePageException(PageContextImpl.java:898)
    org.apache.jasper.runtime.PageContextImpl.handlePageException(PageContextImpl.java:827)
    org.apache.jsp.Address_jsp._jspService(Address_jsp.java:92)
    org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:68)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:376)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:320)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:265)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
root cause

java.lang.NoSuchMethodError: hu.flux.helper.NameAndAddress.print(Ljavax/servlet/jsp/JspWriter;)V
    org.apache.jsp.Address_jsp._jspService(Address_jsp.java:81)
    org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:68)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:376)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:320)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:265)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
note The full stack trace of the root cause is available in the Apache Tomcat/7.0.2 logs.

Apache Tomcat/7.0.2

При вызове из JSP я могу сделать вызов классу с помощью JspWriter, добавив следующий код:

public void print(JspWriter out) throws java.io.IOException 
    { print (new PrintWriter(out)); }

Однако, при попытке использовать JspWriter из консольного приложения (для тестирования - я не думаю, что кому-то когда-либо понадобится использовать JspWriter в консоли!), Вышеуказанная ошибка консоли перемещается в эту функцию.

Если печать (выход из JspWriter) может решить проблему для JSP, не должна ли она также решить проблему для консольных приложений?

Более того, если JspWriter является объектом Writer, не должен ли он всегда быть объектом Writer, независимо от того, вызывается ли он из консоли или из JSP?

Ответы [ 6 ]

3 голосов
/ 03 октября 2010

Это исключение говорит о том, что ваш код JSP не был перекомпилирован после того, как вы изменили print(JspWriter) на print(Object), поэтому он все еще пытается вызвать print(JspWriter) и не может его найти.

Для принудительной перекомпиляции вы можете изменить страницу JSP.

1 голос
/ 03 октября 2010

То, что вы опубликовали, должно работать, так как PrintWriter и JspWriter являются подклассами Writer (и, конечно, оба являются подклассами Object).Кажется, что-то не так с вашим тестовым кодом или с вашей средой.

Возможно, вы можете попробовать упрощенный пример и посмотреть, работает ли он, а затем собрать его оттуда.Я могу предложить начать здесь:

public class Test
{
    public void print(Writer writer) throws IOException
    {
        if (writer == null)
            System.out.println("Null writer");
        else
        {
            writer.write("hello");
            writer.flush();
        }
    }

    public static void main(String args[]) throws IOException
    { 
        Test test = new Test();

        System.out.print("Testing PrintWriter...");
        PrintWriter p = new PrintWriter("d:/temp/pwriter_text.txt");
        test.print(p);
        System.out.print("Tested PrintWriter...");

        System.out.print("Testing JspWriter...");
        JspWriter j = null;
        test.print(j);
        System.out.print("Tested JspWriter...");
    }
}

Это должно скомпилировать и запустить.Во второй раз, когда вызывается test.print(), передается JspWriter будет null, но вы не должны получать NoSuchMethodError.Если это работает, возьмите код и протестируйте его на страницах вашего сервлета / JSP.Надеюсь, это поможет вам найти проблему.

1 голос
/ 03 октября 2010

Это потому, что компилятор Java пытается найти метод PrintWriter.print в объекте JspWriter. Хотя он имеет метод печати, этот метод не соответствует, потому что он из другого класса. Java не поддерживает типизацию утки и делает все возможное, чтобы ее предотвратить.

Также считается плохой практикой использовать исключения в логике программирования.

Тебе придется делать что-то вроде

    try
    { 
       if (out instanceof PrintWriter) {
          ((PrintWriter) out).print(this.formattedString()); 
       } else if (out instanceof JspWriter) {
          ((JspWriter) out).print(this.formattedString()); 
       } else {
          throw new IllegalArgumentException("NameAndAddress.print expected ether a PrintWriter or a JspWriter but received a " + out.getClass().getName());
       }
    catch (Exception ex)
    { System.err.println("\"out\" is not a printable type: " + ex); }

Кстати: методы в Java должны начинаться со строчной буквы по соглашению.

0 голосов
/ 03 октября 2010

Ваш print () передает объект в PrintWriter. Но когда вы передаете JspWriter, который не является PrintWriter, приведение не выполняется.

Однако PrintWriter и JspWriter являются потомками Writer. Можете ли вы изменить свой print() метод для принятия Writer вместо Object, а затем использовать метод Writer.write () в print()? Это общее для обоих классов.

Это:

public void print(Writer writer) {
    try {
        writer.write(this.FormattedString());
    } catch (IOException e) {
        // log something...
    }
}
0 голосов
/ 03 октября 2010

Итак, вы начинаете свой метод с приведения к PrintWriter, так что, возможно, jvm оптимизировал этот метод для вас.Поскольку JspWriter не имеет подкласса от PrintWriter, лучше всего написать два метода:

public void print(JspWriter out) 
{ 
    if (out == null) return;
    try {
        out.print(this.FormattedString());
    } Except (IOException e) {
        // handle error 
    }
}

public void print(PrintWriter out) 
{ 
    if (out == null) return;
    try {
        out.print(this.FormattedString());
    } Except (IOException e) {
        // handle error 
    }
}

Если бы только JspWriter и PrintWriter имели общий интерфейс ... вздох.

0 голосов
/ 03 октября 2010

JspWriter не является PrintWriter

Вы можете обернуть оригинального писателя внутри писателя следующим образом:

if (out instance of Writer) {
 PrintWriter p = new PrintWriter((Writer) out));
 p.print...
}
...