java http request Required String parameter 'Username' is not present - java

I have a spring boot server running that accepts http request.
I have tested it extensively with curl and it works perfectly.
However when I try to send a request and receive a response in a java client I get:
java.io.IOException: Server returned HTTP response code: 400 for URL:
and on the server side I get:
[org.springframework.web.bind.MissingServletRequestParameterException: Required String parameter 'Username' is not present]
Here is the spring boot method I am trying to use:
#PostMapping(path="/CreateAccount") // Map ONLY POST Requests
public #ResponseBody String CreateUser (#RequestParam String Username
, #RequestParam String Password) {
// #ResponseBody means the returned String is the response, not a view name
// #RequestParam means it is a parameter from the GET or POST request
//make sure the username and password is valid input
if (!validateInput(Username) || !validateInput(Password))
{
return "Username and Password cannot be blank";
}
//make sure the username is unique
//check if Username is equal to any other User's username
User u = findByUsername(Username);
//if a user was found in the table
if ( !(u == null) )
{
return "Username already taken\nPlease choose another";
}
//if we are here we are clear to make a new user
User n = new User();
n.setUsername(Username);
n.setPassword(Password);
n.setRole("Player");
userRepository.save(n);
//THIS CAUSES AN ERROR
//create a stat object to be added to the table
Stats s = new Stats();
s.setUsername(Username);
statRepository.save(s);
//create a token for the user
String usrToken = createToken(tokenSize);
//add the username and token to hashmap
userTokens.put(Username, usrToken);
//return this user's token
return usrToken;
}
And here is my client:
public static void CreateAccount(String username, String password)
{
try
{
String s = serverURL + "/CreateAccount";
URL url = new URL(s);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Accept", "application/json");
connection.setRequestProperty("Content-Type", "application/json; utf-8");
connection.setDoOutput(true);
String json = "[{\n\"Username\"=\"Jake\",\"Password\"=\"123\"\n}]";
System.out.println(json);
OutputStream os = connection.getOutputStream();
DataOutputStream out = new DataOutputStream( os );
byte[] input = json.getBytes("utf-8");
out.writeUTF(json);
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String response = br.readLine();
System.out.println(response);
}
catch (Exception e)
{
System.out.println("#");
System.out.println(e);
}
}
I thought it had to do with my json formatting but I've tried over and over and no matter how I format it I get the same error.

If you want send json object, use this code for example:
#PostMapping(path="/CreateAccount")
public #ResponseBody String CreateUser (#RequestBody User user) {
if (user == null)
{
return "User cannot be blank";
}
User u = findByUsername(user.Username);
// your code...
return usrToken;
}

Related

Java HttpURLConnection status code 302

I'm trying to get this code block to run but I keep getting a 302. I've tried to show the flow of the code. I just don't know what's wrong.
import java.net.HttpURLConnection;
import java.util.HashMap;
import java.util.Map;
import java.util.Base64;
public class AuthenticateLoginLogoutExample {
public static void main(String[] args) throws Exception {
new AuthenticateLoginLogoutExample().authenticateLoginLogoutExample(
"http://" + Constants.HOST + "/qcbin",
Constants.DOMAIN,
Constants.PROJECT,
Constants.USERNAME,
Constants.PASSWORD);
}
public void authenticateLoginLogoutExample(final String serverUrl,
final String domain, final String project, String username,
String password) throws Exception {
RestConnector con =
RestConnector.getInstance().init(
new HashMap<String, String>(),
serverUrl,
domain,
project);
AuthenticateLoginLogoutExample example =
new AuthenticateLoginLogoutExample();
//if we're authenticated we'll get a null, otherwise a URL where we should login at (we're not logged in, so we'll get a URL).
It's this next line when it starts on the isAuthenticated() method.
String authenticationPoint = example.isAuthenticated();
Assert.assertTrue("response from isAuthenticated means we're authenticated. that can't be.", authenticationPoint != null);
//do a bunch of other stuff
}
So we go into the isAuthenticated method:
public String isAuthenticated() throws Exception {
String isAuthenticateUrl = con.buildUrl("rest/is-authenticated");
String ret;
Then here on this next line trying to get the response. con.httpGet
Response response = con.httpGet(isAuthenticateUrl, null, null);
int responseCode = response.getStatusCode();
//if already authenticated
if (responseCode == HttpURLConnection.HTTP_OK) {
ret = null;
}
//if not authenticated - get the address where to authenticate
// via WWW-Authenticate
else if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) {
Iterable<String> authenticationHeader =
response.getResponseHeaders().get("WWW-Authenticate");
String newUrl =
authenticationHeader.iterator().next().split("=")[1];
newUrl = newUrl.replace("\"", "");
newUrl += "/authenticate";
ret = newUrl;
}
//Not ok, not unauthorized. An error, such as 404, or 500
else {
throw response.getFailure();
}
return ret;
}
That jumps us to another class and into this method:
public Response httpGet(String url, String queryString, Map<String,
String> headers)throws Exception {
return doHttp("GET", url, queryString, null, headers, cookies);
}
The doHttp takes us here. type = "GET", url = "http://SERVER/qcbin/rest/is-authenticated", the rest are all empty.
private Response doHttp(
String type,
String url,
String queryString,
byte[] data,
Map<String, String> headers,
Map<String, String> cookies) throws Exception {
if ((queryString != null) && !queryString.isEmpty()) {
url += "?" + queryString;
}
HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection();
con.setRequestMethod(type);
String cookieString = getCookieString();
prepareHttpRequest(con, headers, data, cookieString);
This con.connect() on the next line never connects.
con.connect();
Response ret = retrieveHtmlResponse(con);
updateCookies(ret);
return ret;
}
The prepareHttpRequest code:
private void prepareHttpRequest(
HttpURLConnection con,
Map<String, String> headers,
byte[] bytes,
String cookieString) throws IOException {
String contentType = null;
//attach cookie information if such exists
if ((cookieString != null) && !cookieString.isEmpty()) {
con.setRequestProperty("Cookie", cookieString);
}
//send data from headers
if (headers != null) {
//Skip the content-type header - should only be sent
//if you actually have any content to send. see below.
contentType = headers.remove("Content-Type");
Iterator<Entry<String, String>>
headersIterator = headers.entrySet().iterator();
while (headersIterator.hasNext()) {
Entry<String, String> header = headersIterator.next();
con.setRequestProperty(header.getKey(), header.getValue());
}
}
// If there's data to attach to the request, it's handled here.
// Note that if data exists, we take into account previously removed
// content-type.
if ((bytes != null) && (bytes.length > 0)) {
con.setDoOutput(true);
//warning: if you add content-type header then you MUST send
// information or receive error.
//so only do so if you're writing information...
if (contentType != null) {
con.setRequestProperty("Content-Type", contentType);
}
OutputStream out = con.getOutputStream();
out.write(bytes);
out.flush();
out.close();
}
}
And the getCookieString method:
public String getCookieString() {
StringBuilder sb = new StringBuilder();
if (!cookies.isEmpty()) {
Set<Entry<String, String>> cookieEntries =
cookies.entrySet();
for (Entry<String, String> entry : cookieEntries) {
sb.append(entry.getKey()).append("=").append(entry.getValue()).append(";");
}
}
String ret = sb.toString();
return ret;
}
Does anyone have any idea what went wrong? I don't know why it keeps returning a 302.
EDIT: Added chrome developer image as requested.
I haven't followed your entire code, but http 302 means a redirection
https://en.wikipedia.org/wiki/HTTP_302
Depending on the kind of redirection, that could work smoothly or not. For instance the other day I faced a http to https redirection and I have to solve it checking the location header manually.
What I would do is to check first the headers in the browser, in Chrome go to Developer Tools, Network and check the Response Headers (screenshot). You should see there for a 302 response a Location Header, with the new URL you should follow.
302 means there's a page there, but you really want a different page (or you want this page and then that other page). If you look at the headers you get back from the server when it gives you a 302, you'll probably find a "Location:" header telling you where to query next, and you'll have to write yet another transaction.
Browsers interpret the 302 response and automatically redirect to the URL specified in the "Location:" header.

Jersey HTTP response 200 OK but returning content wrong (checking request)

This is a follow-up question to the one I asked yesterday.
The log-in page is supposed to redirect to main page after correct username and password input, with server side returning an empty string (""). If either is incorrect, server side code returns "Username or Password are incorrect".
The page functionality worked well but when I was testing using my client side code using a correct pair of username and password, it returns "Username or Password are incorrect", with response returning 200OK.
Below is my client side code:
public static void main(String[] args){
ClientConfig config = new ClientConfig();
Client client = ClientBuilder.newClient(config);
WebTarget target = client.target("http://localhost:8080
/qa-automation-console").path("authenticate");
Form form = new Form();
form.param("username", "username");
form.param("password", "password");
Response response = target.request().post(Entity.form(form));
//The response was 200OK.
System.out.println(response.readEntity(String.class));
}
Instead of other problems including HTML and Web.xml dependency, now I suspect the client code I wrote was not correct and when the request is sent it does not contain the correct username and password. The server side code is below:
#POST
#Produces("text/plain")
#Path("authenticate")
public String authenticate(#Context HttpServletRequest req, #QueryParam("username")
String username, #QueryParam("password") String password)
throws Exception {
Environments environments = new DefaultConfigurationBuilder().build();
final ALMProfile profile = new ALMProfile();
profile.setUrl(environments.getAutomation().getAlmProfile().getUrl());
profile.setUsername(username);
if ( !Strings.isNullOrEmpty(password) ) {
String encryptedPassword = EncryptionUtils.encrypt(password);
profile.setPassword(encryptedPassword);
}
try (ALMConnection connection = new ALMConnection(profile);) {
if (connection.getOtaConnector().connected()) {
req.getSession(true).setAttribute("username", username);
req.getSession(true).setAttribute("password", profile.getPassword());
return "";
}
} catch (Exception e) {
e.printStackTrace();
return "Username or Password are incorrect";
}
return "Username or Password are incorrect";
}
Can someone point out if the client code submits the correct request?
First of all, you probably need to check what's in your stack trace. And the value of username and password. I suspect them to be null.
Secondly, I think the problem is coming from the #QueryParam annotation.
You must use instead #FormParam
You use QueryParam when your url contain params as:
www.test.com/test?username=test
When you're sending data in a Form, you must use the annotation #FormParam

Accessing Spring Rest with 404 error

I am using Spring MVC in my project and while mapping user request to a URI, I get the 404 error. But there are other controllers where i'm able to access it.
Working controller
#RequestMapping(value = "groupview.htm", method = RequestMethod.GET)
public String showGroups(
#ModelAttribute("groupRegistrationDTO") GroupRegistrationDTO groupRegistrationDTO,
BindingResult result, Model model,
HttpServletRequest httpServletRequest) {
GroupsResultDTO groupsResultDTO = manageGroupBusiness.getGroups(
groupRegistrationDTO, result, model);
return "showGroups";
}
Testing with java class showing desired output
private static void wsRequest(String jsonInput) {
try {
URL url = new URL("http://localhost:5080/myservlet/groupview.htm");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Accept","*/*");
conn.setRequestProperty("Authorization", "Basic "
+ getBasicAuthenticationEncoding());
if (conn.getResponseCode() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ conn.getResponseCode());
}
BufferedReader br = new BufferedReader(new InputStreamReader(
(conn.getInputStream())));
String output;
System.out.println("Output from Server .... \n");
while ((output = br.readLine()) != null) {
System.out.println(output);
}
conn.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Now i have another controller which is a restful service when i try to test that using poster plugin or through java net URL connection(using requestmethod post). I get 404 response code.
Trying to access with URL :
http://localhost:5080/myservlet/authAndRegDevice.htm
Rest Service Controller
#RequestMapping(value = "authAndRegDevice.htm", method = RequestMethod.POST)
#ResponseBody
public String authenticateAndRegisterDevice(
#RequestBody String notificationJsonRequest){
return "success";
}
Why would the second controller give the 404 error while the first one working.
Can some one please help me to get out of this issue
This issue can be closed here as i have raised another post with detailed question and with the exact failure where i was facing.
Bypass spring security with java URL connection

jax-rs returned String

I am programming a jax-rs webservice which I want to contact from a java-program. I defined a #POST method which receives a String-array as input and is supposed to return a boolean value.
But really, how can i access this return value in java? I've been searching the web for several hours now, everybody writes example methods which return Strings or something else, but nobody shows how to access the returned value from another java program.
Here is the code from the program that contacts the #POST method:
ObjectOutputStream oos = null;
String[] login = {"XXXXXX","XXXXXXX"};
try {
login[1] = PasswordGenerator.hashPassword(login[1]);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
URL url = new URL("XXXXX/XXXXXXX/XXXXXX/users/login/1");
try {
// creates a HTTP connection
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
httpConn.setUseCaches(false);
httpConn.setDoOutput(true);
httpConn.setRequestMethod("POST");
httpConn.setRequestProperty("Boolean", "application/xml");
OutputStream outputStream = httpConn.getOutputStream();
oos = new ObjectOutputStream(outputStream);
outputStream.close();
System.out.println();
} finally {
if (oos != null) {
oos.close();
}
}
}
What I want to know is: What happens after I closed my outputStream? I mean, i started the POST method, but it is supposed to return a boolean value. Where is this value? How can I access it???
JAX-RS 2.0 has a Client API that provides you with a fluent API to retrieve the content of the response:
Client client = ClientBuilder.newClient();
Boolean result = client.target("http://localhost:8080/xxx/")
.path("user/login/1")
.request(MediaType.TEXT_PLAIN_TYPE)
.post(Entity.entity(login, MediaType.APPLICATION_XML) , Boolean.class);
But unfortunately, you'll need a custom MessageBodyWriter to convert the String[] into an XML document. Maybe you should change your server-side method (and client) to manipulate a DTO - a POJO with 2 fields, username and password - and annotated with #XmlRootElement ?
something like that:
(client-side)
Credentials credentials = new
credentials.setUsername("foo");
credentials.setUsername("hashedPwd");
Client client = ClientBuilder.newClient();
Boolean result = client.target("http://xxxxx")
.path("/user/login/1")
.request(MediaType.TEXT_PLAIN_TYPE)
.post(Entity.entity(credentials, MediaType.APPLICATION_XML) , Boolean.class);
System.out.println("Result: " + result);
(server-side)
#Path("/login/{id}")
#POST
public Boolean test(#PathParam("id") String login, Credentials credentials) {
...
}

RestFB: Using a facebook app to get the users Access Token

This is what i have:
static AccessToken accessToken = new DefaultFacebookClient().obtainExtendedAccessToken("<my app id>", "<my app secret>");
static FacebookClient client = new DefaultFacebookClient();
public static void main(String args[]) {
System.out.print("Enter Your Status: ");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String status= null;
try {
userName = br.readLine();
System.out.println("..........");
} catch (IOException ioe) {
System.out.println("!");
System.exit(1);
}
FacebookType publishMessageResponse =
client.publish("me/feed", FacebookType.class,
Parameter.with("message", status));
So first line gets the token and stores it as type AccessToken but what good does that do to me because next line i need to provide the access token as a string and i can't convert it. Any Help?
First of all don't confuse app token with user token (more info)
To get user token you have to
Provide a way for user to authenticate against Facebook (more info) and receive "code" - an encrypted string unique to each login request.
Get the user token using this code.
You can get user token with pure RestFB the following way:
private FacebookClient.AccessToken getFacebookUserToken(String code, String redirectUrl) throws IOException {
String appId = "YOUR_APP_ID";
String secretKey = "YOUR_SECRET_KEY";
WebRequestor wr = new DefaultWebRequestor();
WebRequestor.Response accessTokenResponse = wr.executeGet(
"https://graph.facebook.com/oauth/access_token?client_id=" + appId + "&redirect_uri=" + redirectUrl
+ "&client_secret=" + secretKey + "&code=" + code);
return DefaultFacebookClient.AccessToken.fromQueryString(accessTokenResponse.getBody());
}
The call is simple:
FacebookClient.AccessToken token = getFacebookUserToken(code, redirectUrl);
String accessToken = token.getAccessToken();
Date expires = token.getExpires();
In addition to what Jack said about AccessToken.getAccessToken() returning the string value of accessToken, you can avoid instantiating DefaultFacebookClient twice by extending DefaultFacebookClient like this:
import com.restfb.DefaultFacebookClient;
public class LoggedInFacebookClient extends DefaultFacebookClient {
public LoggedInFacebookClient(String appId, String appSecret) {
AccessToken accessToken = this.obtainAppAccessToken(appId, appSecret);
this.accessToken = accessToken.getAccessToken();
}
}
Try the following code:
AccessToken accessToken = new DefaultFacebookClient().obtainAppAccessToken(appid,appsecret);
String token=accessToken.getAccessToken();
Per restfb.FacebookClient.AccessToken, you should be able to call accessToken.getAccessToken() -- that should return the String you are looking for.
This will work
AccessToken accessToken = new DefaultFacebookClient().obtainAppAccessToken("XXXX", "XXXX");
String token=accessToken.getAccessToken();
DefaultFacebookClient facebookClient = new DefaultFacebookClient(token);

Categories