Malformed URL when connecting applet to servlet - java

I'm trying to access a servlet from a java applet and set the servlet's response in the applet's text field.
I'm using tomcat 7.0 and my jre/jdk are fully updated.
The servlet runs fine (correct output in the browser) when invoked from the browser as localhost:8080/hello/hello?query=select * from airports
(where airports is the name of the database)
However when i run the applet in appletviewer, i get a Malformed URL exception thrown..
Code for Applet:
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
/*
<applet code="lab101" width=500 height=270>
</applet>
*/
public class lab101 extends Applet implements ActionListener{
TextArea t;
Panel p,q,r;
CheckboxGroup c;
Checkbox ins,dis,del,update; //Checkboxes are included just for testing purposes.
TextField f;
Label l1;
Button b;
public void init(){
setLayout(new FlowLayout());
b=new Button("Run");
l1=new Label("Query:");
c=new CheckboxGroup();
t=new TextArea("",10,50);
p=new Panel();
q=new Panel();
r=new Panel();
p.add(t);
ins=new Checkbox("Insert",c,false);
dis=new Checkbox("Display",c,true);
del=new Checkbox("Delete",c,false);
update=new Checkbox("Update",c,false);
f=new TextField(50);
q.add(ins);
q.add(dis);
q.add(del);
q.add(update);
r.add(l1);
r.add(f);
r.add(b);
b.addActionListener(this);
add(p);
add(q);
add(r);
try{
URL url=new URL("127.0.0.1:8080/hello/hello?query=select * from airports");
URLConnection servletconnection=url.openConnection();
servletconnection.setDoInput(true);
InputStream in=servletconnection.getInputStream();
String s="";
int ch;
loop:while(1>0){
ch=in.read();
if(ch==-1) break loop;
else s+=(char)ch;
}
t.setText(s);
}//try close
catch(MalformedURLException e){
t.setText("Malformed URL Exception occured.");}
catch(IOException e){
t.setText("IO exception occured");}
}
public void actionPerformed(ActionEvent ae){
}
public void start(){
}
public void paint(Graphics g){
}
}//class ends
Code for servlet:
import java.io.*;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.sql.*;
public class hello extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException {
response.setContentType("text/plain");
PrintWriter out=response.getWriter();
String query=request.getParameter("query");
Connection link=null;
Statement statement=null;
ResultSet results=null;
try{
Class.forName("org.postgresql.Driver");
String url = "jdbc:postgresql://localhost:5432/test";
link=DriverManager.getConnection(url,"postgres","hooligan");
out.println("Successful connection");
}
catch(ClassNotFoundException e){
out.println("Unable to load driver");
}
catch(SQLException e){
out.println("Cannot connect to database");
}
try{
statement=link.createStatement();
//String select="select * from airports";
results=statement.executeQuery(query);
}
catch(SQLException e){
out.println("Cannot execute query");
e.printStackTrace();
}
try{
out.println();
while(results.next()){
out.println("Name: " + results.getString(1));
out.println("Location: " + results.getString(2));
//System.out.println("Account no: " + results.getInt(3));
System.out.println();}
}
catch(SQLException e){
out.println("Error retrieving data");
}
try{
link.close();}
catch(SQLException e){
out.println("Unable to disconnect");}
out.close();
out.flush();
}}
Any thoughts?
P.S. i also noticed that if i use localhost instead of 127.0.0.1 i get a Security Exception thrown (Probably because the applet is unsigned?)

There are 2 (actually 3) problems:
First, an applet is only allowed to fire HTTP requests on the exact URL base as where the applet is been served from. You can obtain it by Applet#getCodeBase() which needs to be used as follows:
URL url = new URL(getCodeBase(), "hello?query=select * from airports");
URLConnection connection = url.openConnection();
// ...
Second, your query string contains illegal characters for use in URLs (space, asterisk). You need to use URLEncoder#encode() to URL-encode the query string.
String query = URLEncoder.encode("select * from airports", "UTF-8");
URL url = new URL(getCodeBase(), "hello?query=" + query);
URLConnection connection = url.openConnection();
// ...
You also need to ensure that you open the HTML/JSP page with the applet in the browser on the same base URL as where the servlet runs. E.g. http://localhost:8080/hello/pagewithapplet.html and thus not from commandline or by an appletviewer or something. The applet really needs to be served from the same webserver as where the servlet runs.
Unrelated to the concrete problem as stated in the question, your third problem is that sending a plain SQL statement as request parameter is a very bad idea. What if a hacker decompiles your applet and figures how the applet-servlet communication is done and then modifies the SQL statement into something else, such as delete from airports?
Do not do the SQL in the applet, do it in the servlet only and let the applet send specific commands only, such as hello?query=list_airports (which is actually still open for further optimization, think of a REST webservice, but that's left up to you as an exercise).

URL url=new URL("127.0.0.1:8080/hello/hello?query=select * from airports")
is not a valid URL.

Related

HTTP Callback in Java

I'm trying to write some code to handle the process of an HTTP callback in Java.
I have very little knowledge of Java and was hopping you could lend me a hand or point me in the right way.
I want to call the script from a page that will listen for a POST from other machine with some parameters and their values.
I then want the script to save them somewhere (a file or a database).
Any help would be really appreciated.
For further clarification, I want to create a servlet on a specific URL to handle a HTML post from another machine and receive all parameters and their values and insert them into a database for example.
Another edit, got to this code so far:
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.sql.*;
public class CallbackServlet extends HttpServlet
{
public void doPost(HttpServletRequest req,HttpServletResponse res)throws
IOException,ServletException
{
String instId=req.getParameterValues("instId")[0];
String cartId=req.getParameterValues("cartId")[0];
String desc=req.getParameterValues("desc")[0];
String cost=req.getParameterValues("cost")[0];
String amount=req.getParameterValues("amount")[0];
String currency=req.getParameterValues("currency")[0];
String name=req.getParameterValues("name")[0];
String transId=req.getParameterValues("transId")[0];
String transStatus=req.getParameterValues("transStatus")[0];
String transTime=req.getParameterValues("transTime")[0];
String cardType=req.getParameterValues("cardType")[0];
Connection conn = null;
Statement stmt = null;
PrintWriter out=res.getWriter();
try
{
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/orders", "root", "root");
stmt = conn.createStatement();
int i=stmt.executeUpdate("insert into orderdetails values('"+transId+"','"+instId+"','"+cartId+"','"+desc+"'"+cost+"','"+amount+"','"+currency+"','"+name+"','"+transStatus+"','"+transTime+"','"+cardType+")");
if(i>0)
out.println("Inserted Successfully");
else
out.println("Insert Unsuccessful");
}
catch(SQLException ex)
{
ex.printStackTrace();
}
}
}
I can't test it atm unfortunately. Could you guys take a look at it and point out any mistakes/improvements?
Cheers
Probably easiest way for this would be to use Servlet api with some Java application server (tomcat, jetty, ...).Look at http://www3.ntu.edu.sg/home/ehchua/programming/java/javaservlets.html

Issue in running code using JasperReports API on different machines

I created a Java project which will use JasperReports API. I have tested this inside and outside NetBeans (same machine) and it works fine. But when I try to run it on another machine the report wont load.
My code is:
package reportmonitory;
import java.sql.*;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.swing.JRViewer;
import javax.swing.*;
public class monthlyreport extends JFrame {
Connection con;
Statement stmt;
ResultSet rs;
void showReport() {
try {
String host = "jdbc:mysql://192.168.10.11/rmcdb";
String uName = "root";
String uPass = "";
Class.forName("com.mysql.jdbc.Driver").newInstance();
con = DriverManager.getConnection(host, uName, uPass);
stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
String reportName = "reports/finalreport.jasper";
java.io.InputStream is = this.getClass().getClassLoader().getResourceAsStream(reportName);
JasperPrint print = JasperFillManager.fillReport(is, null, con);
JRViewer viewer = new JRViewer(print);
viewer.setOpaque(true);
viewer.setVisible(true);
this.add(viewer);
this.setSize(1000, 1000);
this.setVisible(true);
this.setDefaultCloseOperation(HIDE_ON_CLOSE);
} catch (Exception ex) {
System.out.println("CAUSE: " + ex.getCause());
System.out.println("MESSAGE" + ex.getMessage());
System.out.println("LOCAL MESSAGE" + ex.getLocalizedMessage());
ex.printStackTrace();
}
}
public static void main(String args[]) {
new monthlyreport().showReport();
}
}
Here are some suggestions / things to look into:
Port forwarding for databases behind firewalls
Specify port in case the database's connection port has been changed
Make sure 'reports/finalreport.jasper' exists
Packaging (due to project moving around)
Ensure all .jar's / JasperReport API files are there
All other files this project calls are there
Network problem / not finding hostname: 192.168.10.11
EDIT:
The error comes from being unable to find 'npa logo.jpg'. Make sure it exists on the correct path. I notice you are looking for it on 'C:\Users\mwaluda' and you are running JaspterReports on C:\Users\Aboud. If this is a different machine, would that path still be valid?

Swing application to applet

I have made a basic swing application to input data into MySQL server. It is for some reason not accessing the driver to connect to the database. Here is the code. Thanks in advance for all the answers
import javax.swing.*;
import java.awt.event.*;
import java.sql.*;
public class Action extends JApplet {
public void init() {
}
public Action() {
JButton button = new JButton("Click here");
button.addActionListener(new EventHandler());
add(button);
}
}
public class EventHandler implements ActionListener{
public void actionPerformed(ActionEvent e) {
try{
Class.forName("com.mysql.jdbc.Driver").newInstance();
String url = "jdbc:mysql://localhost:3306/testgui";
Connection con= DriverManager.getConnection(url,"root", null);
String str = JOptionPane.showInputDialog(null,"Enter type");
String abc = JOptionPane.showInputDialog(null,"Enter number");
Statement st= con.createStatement();
st.executeUpdate("insert into tb1 values (null,'"+str+"',"+abc+")");
}
catch(Exception e1){
e1.printStackTrace();
}
}
}
please read What Applets Can and Cannot Do
Unsigned applets cannot perform the following operations:
They cannot access client resources such as the local filesystem, executable files, system clipboard, and printers.
They cannot connect to or retrieve resources from any third party server (any server other than the server it originated from).
They cannot load native libraries.
They cannot change the SecurityManager.
They cannot create a ClassLoader.
They cannot read certain system properties. See System Properties for a list of forbidden system properties.
maybe simple and possible way is look at Java Web Start, completed by #Andrew Thompson

Why does this HTTP servlet behave inconsistently?

An intranet site has a search form which uses AJAX to call a servlet on a different domain for search suggestions.
This works in Internet Explorer with the intranet domain being a "trusted site" and with cross-domain requests enabled for trusted sites, but doesn't work in Firefox.
I have tried to work around the problem by creating a servlet on the intranet server, so there's a JS call to my servlet on the same domain, then my servlet calls the suggestions servlet on the other domain. The cross-domain call is server-side, so it should work regardless of browser settings.
The AJAX call and my servlet's call to the other servlet both use a HTTP POST request with arguments in the URL and empty request-content.
The reason I'm sticking with POST requests is that the JS code is all in files on the search server, which I can't modify, and that code uses POST requests.
I've tried calling the customer's existing suggestions servlet with a GET request, and it produces a 404 error.
The problem is that the result is inconsistent.
I've used System.out.println calls to show the full URL and size of the result on the server log.
The output first seemed to change depending on the calling browser and/or website, but now seems to change even between sessions of the same browser.
E.g. entering "g" in the search box, I got this output from the first few tries on the Development environment using Firefox:
Search suggestion URL: http://searchdev.companyname.com.au/suggest?q=g&max=10&site=All&client=ie&access=p&format=rich
Search suggestion result length: 64
Initial tries with Firefox on the Test environment (different intranet server but same search server) produced a result length of 0 for the same search URL.
Initial tries with Internet Explorer produced a result length of 0 in both environments.
Then I tried searching for different letters, and found that "t" produced a result in IE when "g" hadn't.
After closing the browsers and leaving it for a while, I tried again and got different results.
E.g. Using Firefox and trying "g" in the Development environment now produces no result when it was previously producing one.
The inconsistency makes me think something is wrong with my servlet code, which is shown below. What could be causing the problem?
I think the search suggestions are being provided by a Google Search Appliance, and the JS files on the search server all seem to have come from Google.
The actual AJAX call is this line in one file:
XH_XmlHttpPOST(xmlhttp, url, '', handler);
The XH_XmlHttpPOST function is as follows in another file:
function XH_XmlHttpPOST(xmlHttp, url, data, handler) {
xmlHttp.open("POST", url, true);
xmlHttp.onreadystatechange = handler;
xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xmlHttp.setRequestHeader("Content-Length",
/** #type {string} */ (data.length));
XH_XmlHttpSend(xmlHttp, data);
}
Here is my servlet code:
package com.companyname.theme;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Properties;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class suggest extends HttpServlet {
Properties props=null;
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String result = "";
String args = req.getQueryString();
String baseURL = props.getProperty("searchFormBaseURL");
String urlStr = baseURL + "/suggest?" + args;
System.out.println("Search suggestion URL: " + urlStr);
try {
int avail, rCount;
int totalCount = 0;
byte[] ba = null;
byte[] bCopy;
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
os.write("".getBytes());
os.close();
InputStream is = conn.getInputStream();
while ((avail = is.available()) > 0) {
if (ba == null) ba = new byte[avail];
else if (totalCount + avail > ba.length) {
// Resize ba if there's more data available.
bCopy = new byte[totalCount + avail];
System.arraycopy(ba, 0, bCopy, 0, totalCount);
ba = bCopy;
bCopy = null;
}
rCount = is.read(ba, totalCount, avail);
if (rCount < 0) break;
totalCount += rCount;
}
is.close();
conn.disconnect();
result = (ba == null ? "" : new String(ba));
System.out.println("Search suggestion result length: " + Integer.toString(result.length()));
} catch(MalformedURLException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
}
PrintWriter pw = resp.getWriter();
pw.print(result);
}
#Override
public void init() throws ServletException {
super.init();
InputStream stream = this.getClass().getResourceAsStream("/WEB-INF/lib/endeavour.properties");
props = new Properties();
try {
props.load(stream);
stream.close();
} catch (Exception e) {
// TODO: handle exception
}
}
}
Solution: don't rely on InputStream.available().
The JavaDoc for that method says it always returns 0.
HttpURLConnection.getInputStream() actually returns a HttpInputStream, in which available() seems to work but apparently sometimes returns 0 when there is more data.
I changed my read loop to not use available() at all, and now it consistently returns the expected results.
The working servlet is below.
package com.integral.ie.theme;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Properties;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class suggest extends HttpServlet implements
javax.servlet.Servlet {
Properties props=null;
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//super.doPost(req, resp);
final int maxRead=200;
String result="";
String args=req.getQueryString();
String baseURL=props.getProperty("searchFormBaseURL");
String urlStr=baseURL+"/suggest?"+args;
//System.out.println("Search suggestion URL: "+urlStr);
try {
int rCount=0;
int totalCount=0;
int baLen=maxRead;
byte[] ba=null;
byte[] bCopy;
URL url=new URL(urlStr);
HttpURLConnection conn=(HttpURLConnection)url.openConnection();
conn.setRequestMethod("POST");
// Setting these properties may be unnecessary - just did it
// because the GSA javascript does it.
conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
conn.setRequestProperty("Content-Length","0");
InputStream is=conn.getInputStream();
ba=new byte[baLen];
while (rCount>=0) {
try {
rCount=is.read(ba,totalCount,baLen-totalCount);
if (rCount>0) {
totalCount+=rCount;
if (totalCount>=baLen) {
baLen+=maxRead;
bCopy=new byte[baLen];
System.arraycopy(ba,0,bCopy,0,totalCount);
ba=bCopy;
bCopy=null;
}
}
} catch(IOException e) {
// IOException while reading - allow the method to return
// anything we've read so far.
}
}
is.close();
conn.disconnect();
result=(totalCount==0?"":new String(ba,0,totalCount));
//System.out.println("Search suggestion result length: "
//+Integer.toString(result.length()));
} catch(MalformedURLException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
}
PrintWriter pw=resp.getWriter();
pw.print(result);
}
#Override
public void init() throws ServletException {
super.init();
InputStream stream=this.getClass().getResourceAsStream("/WEB-INF/lib/endeavour.properties");
props=new Properties();
try {
props.load(stream);
stream.close();
} catch (Exception e) {
// TODO: handle exception
}
}
}
Start with a unit test. Servlets are pretty straightforward to unit test and HttpUnit has worked for us.
Debugging Servlet code in a browser and with println calls will cost more time in the long run and it's difficult for someone on SO to digest all of that information to help you.
Also, consider using a JavaScript framework such as JQuery for your AJAX calls. In my opinion there's little reason to touch an xmlHttp object directly now that frameworks will hide that for you.

Execute jdbc applet in browser

import java.sql.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
/*
<applet code="A0" width=250 height=200>
</applet>
*/
public class A0 extends Applet implements ActionListener,ItemListener
{
String msg="";
Button view,delete,create,edit,reapp,exit;
TextField M_head;
int x,i,ans=0,flag;
public void init()
{
setLayout(new FlowLayout(FlowLayout.CENTER,50,3));
view = new Button("view");
delete = new Button("delete");
create = new Button("create");
edit = new Button("edit");
reapp = new Button("reapp");
exit= new Button("exit");
M_head = new TextField(15);
add(view);
add(delete);
add(create);
System.out.println("vikram");
add(edit);
add(reapp);
add(exit);
System.out.println("phaneendra");
add(M_head);
view.addActionListener(this);
delete.addActionListener(this);
create.addActionListener(this);
edit.addActionListener(this);
reapp.addActionListener(this);
exit.addActionListener(this);
M_head.addActionListener(this);
}
public void actionPerformed(ActionEvent ae)
{
String str=ae.getActionCommand();
if(str.equals("view"))
{msg ="1";}
if(str.equals("delete"))
{msg ="2";}
if(str.equals("create"))
{msg ="3";}
if(str.equals("edit"))
{msg ="4";}
if(str.equals("reapp"))
{msg ="5";}
if(str.equals("exit"))
{msg ="6";}
if(msg=="3")
{
try{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
//String filename = "E:/vikram/conn/new/db/north.mdb";
String filename = "./db/north.mdb";
String database = "jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=";
//String url ="jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=D:\\cheminDeMaBaseEtNomdeLaBdd";
database+=filename.trim();
String head = M_head.getText();
String head1 = head.trim();
Connection con = DriverManager.getConnection(database,"","");
Statement doo = con.createStatement();
//String vi ="create table head1 (Reapporder integer, Amount integer)";
String vi="insert into head1 values(1,2);";
boolean i=false;
i=doo.execute(vi);
if(i)
M_head.setText("Failed to insert");
else
M_head.setText("record inserted");
}
catch(Exception err)
{
System.out.println("Error :"+err);
}
}
}
public void itemStateChanged(ItemEvent ie)
{
repaint();
}
public void paint(Graphics g)
{
g.drawString(msg,70,200); //No use
g.drawString("ANSWER=",6,200); // No use
}
}
This is A0.txt
grant {
permission java.lang.RuntimePermission
"accessClassInPackage.sun.jdbc.odbc";
permission java.util.PropertyPermission
"file.encoding", "read";
};
A0.html file
<html>
<head>
</head>
<body>
<applet code=A0 width=250 height=200></applet>
</body>
</html>
This code is executed in Appletviewer command, but not in any browser
As commented by others, you really don't want to do this.
Just create a webservice in the server side (which can be a plain vanilla servlet) and make use of java.net.URLConnection in the applet.
Basic Servlet example:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String action = request.getParameter("action"); // Or request.getPathInfo() whatever you want.
String result = someDAO.doAction(action);
response.getWriter().write(result);
}
Basic Applet example:
URL url = new URL("http://example.com/databaseservlet?action=someaction");
URLConnection connection = url.openConnection();
InputStream result = connection.getInputStream(); // Important. This actually fires the request!
Be careful with SQL injections however. Do in no way pass raw SQL queries as request parameters or pathinfo and use PreparedStatement all the time in the DAO code.
As response data format you can use a plain vanilla String (as given in example) or a XML string or a JSON string or maybe even a fullworthy Java object with a little help of Serialization.
You can't do JDBC on an Applet for security reasons.
You must write an Enterprise Application (in Java, .NET, Python, PHP) and deploy it to an application server. In that application you can publish some WebServices so your Applet can finally access your database.
Something like this:
APPLET <-> APPLICATION SERVER (HTTP communication) <-> BACKEND (database)
Here is a Web Site explaining some security related Applet stuff.

Categories

Resources