Link to home
Start Free TrialLog in
Avatar of Sreejith22
Sreejith22Flag for India

asked on

How to execute a static method twice

Hi all,
In the attached code, as you can see I call the method at.sendRequestString(), twice from main() method.
The first line in sendRequestString() method is Authenticator.setDefault(new MyAuthenticator());

Authenticator is an abstract class and setDefault is a static method in that class.

When I call sendRequestString() for the second time, Authenticator.setDefault(new MyAuthenticator()); is not executed. ie; Authenticator.setDefault gets executed once and only once.
Does this happen because that Authenticator.setDefault is a static method and it will be executed only once?
If yes, how can I make it work for the second time?
My simple Java code is attached. The username and password given in the code are just sample ones.
Please help with an appropriate solution.
Any help in this regard will be well appreciated with points.
Regards,
Sreejith

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Authenticator;
import java.net.MalformedURLException;
import java.net.PasswordAuthentication;
import java.net.URL;
public class GetAuthenticatedData
{
	public String address;
	static String username;
	static String password;
	public GetAuthenticatedData(String address){
		this.address = address;
	}
	public String sendRequestString()
	{
		Authenticator.setDefault(new MyAuthenticator());//BEING STATIC METHOD, SET DEFAULT CALLED ONLY ONCE
	    String str = null;
	    try {
	        URL url = new URL(address);
	        BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
	        
	        while (( str = in.readLine()) != null) {
	        	return str;
	        }
	        in.close();
	    } catch (MalformedURLException e) {
	    	System.out.println("e1"+e);
	    } catch (IOException e) {
	    	System.out.println("e2"+e);
	    }
	    Authenticator.setDefault(null);
		return str;
	}
	public static void main(String args[]){
		username = "username1";
		password = "password1";
		GetAuthenticatedData at = new GetAuthenticatedData("https://" + username +":"+ password + "@www.mybooo.com/core/Dd002wW.php?data={action:'contacts',args:''}");
		System.out.println("value corresponding to username1 and password1"+at.sendRequestString());
		username = "username2";
		password = "password2";
		at = new GetAuthenticatedData("https://" + username +":"+ password + "@www.mybooo.com/core/Dd002wW.php?data={action:'contacts',args:''}");
		System.out.println("value corresponding to username2 and password2 "+at.sendRequestString());
	}
}
class MyAuthenticator extends Authenticator {
	public MyAuthenticator(){
		getPasswordAuthentication();
	}
		protected PasswordAuthentication getPasswordAuthentication() {
			PasswordAuthentication auth = new PasswordAuthentication(GetAuthenticatedData.username, GetAuthenticatedData.password.toCharArray());
	        System.out.println("Username"+auth.getUserName());
	        System.out.println("Password"+new String(auth.getPassword()));
			return auth;
	}
}

Open in new window

Avatar of quincydude
quincydude
Flag of Hong Kong image

Hi, its not Authenticator.setDefault() method do not run twice but some part of code in it does. A static method will keep in memory until being destroyed so the variables in it will keep the same also the whole application cycle if you do not change them. So I think it's the coding of Authenticator.setDefault()  affect the behaviour. You should look at the source code or any documentation to look for the reason.

Quincy
Avatar of Sreejith22

ASKER

Hi quincydude,
Thanks.
Here is the Authenticator.setDefault() method.

Literally, I am seeking a solution, so that I can get out of this mess.
public synchronized static void setDefault(Authenticator a) {
	SecurityManager sm = System.getSecurityManager();
	if (sm != null) {
	    NetPermission setDefaultPermission
		= new NetPermission("setDefaultAuthenticator");
	    sm.checkPermission(setDefaultPermission);
	}
 
	theAuthenticator = a;
    }

Open in new window

I think it's System.getSecurityManager() that plays the trick.
If it get the SecurityManager, the whole piece of code do not execute.
You should find a method to reset it after your sendRequestString() finishes.
System class cannot be instantiated. Then how will I reset it?
Oops, sorry what I just say was completely wrong.
This module is just for checking if system has the rights to change the authenticator. If it do not have the rights, an exception will be thrown.
Quincy,
So you say that this cannot be solved?
I just noticed you got multiple returns in the code but I m not sure if it's related to the problem, but you can test this
        public String sendRequestString()
        {
 
            Authenticator.setDefault(new MyAuthenticator());//BEING STATIC METHOD, SET DEFAULT CALLED ONLY ONCE
            String str = "";
			String aline = null;
            try {
                URL url = new URL(address);
                BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
                
                while (( aline = in.readLine()) != null) {
                       str += aline;
                }
                in.close();
            } catch (MalformedURLException e) {
                System.out.println("e1"+e);
            } catch (IOException e) {
                System.out.println("e2"+e);
            }
            Authenticator.setDefault(null);
            return str;
        }

Open in new window

Avatar of CEHJ
As i mentioned earlier, you should try to reset the important elements (IOW the username and password) of the Authenticator, not the authenticator itself. You can use normal mutator methods to do this and then use the accessor methods to perform the significant method of the Authenticator below. If this doesn't work (you don't have control of when the Authenticator gets called, then use an API such as Apache HttpClient, which will give you more control over the authentication process
protected PasswordAuthentication getPasswordAuthentication() {
	....
	return new PasswordAuthentication(getCurrentUsername(), getCurrentPassword().toCharArray());
}

Open in new window

Below given is the final implementation, by correctly taking into consideration, each of your suggestions and comments. Still the result is the same.

Though, password authentication works correctly for both the combinations, it still does not have any effect in general and the output obtained for second combination is the same as that of the first.
So, this implies that problem is concerned with setDefault rt?

Please help with solution.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Authenticator;
import java.net.MalformedURLException;
import java.net.PasswordAuthentication;
import java.net.URL;
public class GetAuthenticatedData1
{
    public void execute(){
    try {
        URL url = new URL("https://www.mybooo.com/core/Dd002wW.php?data={action:'contacts',args:''}");
        BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
        String str;
        while ((str = in.readLine()) != null) {
        	System.out.println("string from server"+str);
        }
        in.close();
    } catch (MalformedURLException e) {
    	System.out.println(e);
    } catch (IOException e1) {
    	System.out.println(e1);
    }
    }
    public static void main(String args[]){
    	Authenticator.setDefault(new MyAuthenticator1());
    	MyAuthenticator1 at1 = new MyAuthenticator1();
    	at1.setCredentials("usr1","pwd1");
    	GetAuthenticatedData1 ad = new GetAuthenticatedData1();
    	ad.execute();
    	at1.setCredentials("usr2","pwd2");
    	ad.execute();
    }
}
class MyAuthenticator1 extends Authenticator {
	String username = "usr1";
    String password = "pwd1";
	public void setCredentials(String user, String pass){
    	username = user;
    	password = pass;
    	System.out.println("bb"+username+"pwd"+password);
    	getPasswordAuthentication();
    }
    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication(username, password.toCharArray());
    }
}

Open in new window

Put some debug in getPasswordAuthentication to make sure it's getting called and returning what you expect
I changed the password authentication method to debug as follows.

>>  protected PasswordAuthentication getPasswordAuthentication() {
      PasswordAuthentication pa = new PasswordAuthentication(username, password.toCharArray());
      System.out.println("username in password authentication"+pa.getUserName());
          System.out.println("password in password authentication"+new String(pa.getPassword()));
        return pa;
    }

and correct username password combinations are obtained.

Below given is my complete output.

>>bb usr1 pwd pwd1
username in password authentication usr1
password in password authentication pwd1
username in password authentication usr1
password in password authentication pwd1
string from server{groups:['TestG','test','Group2'],contacts:[{usr:'test10',group:'TestG'},{usr:'rhar',group:'TestG'},{usr:'zapata31',group:''},{usr:'pertchiou',group:'Group2'},{usr:'bossone',group:''},{usr:'webmaster',group:'test'},{usr:'demo14',group:''}]}

bb usr2 pwd pwd2
username in password authentication usr2
password in password authentication pwd2
string from server{groups:['TestG','test','Group2'],contacts:[{usr:'test10',group:'TestG'},{usr:'rhar',group:'TestG'},{usr:'zapata31',group:''},{usr:'pertchiou',group:'Group2'},{usr:'bossone',group:''},{usr:'webmaster',group:'test'},{usr:'demo14',group:''}]}

As you can see, for the first time, password authentication is being called twice.
Anyway, the correct combinations ae being used.

You should probably inspect the session handling by the server itself. The only way to do that, insofar as it's possible at all, is to check out all headers between

a. the browser and the site
b your app and the site
I checked the server and it gets usr1 pwd1 combination in the second call also. So this probably  has to get fixed from the code itself rt?
I was just asking the solution for that.
>>I checked the server and it gets usr1 pwd1 combination in the second call also.

What about with the browser?
ASKER CERTIFIED SOLUTION
Avatar of Sreejith22
Sreejith22
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
For the above code tp work, you need to have the following code also.

http://www.source-code.biz/snippets/java/Base64Coder.java.txt

Sun's implementation of HttpURLConnection seems to keep a cache of previous PasswordAuthentication objects returned by an Authenticator. The workaround was to simply fudge an Authorization header.

MyAuthenticator is not needed anymore, nor are calls to setDefault.