HTTP 400 response Servlet - java

The below code is part of a servlet which is taking the cookie value and sending request to another service with the same cookie value with additional headers.
I am getting HTTP 400 response on the responseCode = serviceUrlConnection.getResponseCode(); and on is = serviceUrlConnection.getInputStream();.
With the same input values (cookie and additional headers), I able to get correct output from the service using SOAP UI. Could somebody point out the mistake.
URL serviceURL = new URL(serviceUrlInput);
logger.info(" Validate Test token service Url" + serviceUrlInput);
URLConnection serviceConnection = serviceURL.openConnection();
HttpURLConnection serviceUrlConnection = (HttpURLConnection)serviceConnection;
serviceUrlConnection.setRequestProperty("Content-Type", "application/json");
serviceUrlConnection.setRequestProperty("charset", "UTF-8");
String TestCookieValue = null;
Cookie[] cookies = req.getCookies();
if (cookies != null) {
for (int i = 0; i < cookies.length; i++) {
if (cookies[i].getName().equals("Test")) {
//TestToken = cookies[i].getValue();
TestCookieValue = cookies[i].getValue();
logger.info("Test cookie : " + "Test=" +TestCookieValue);
//serviceUrlConnection.setRequestProperty("Cookie", TestCookie.substring(0, TestCookie.indexOf(';')));
serviceUrlConnection.setRequestProperty("Cookie", "Test=" +TestCookieValue);
break;
}
}
}
//Set the timestamp in the header
Date javaUtilDate = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
String formattedDateTime = formatter.format(javaUtilDate);
serviceUrlConnection.setRequestProperty("timestamp", formattedDateTime);
logger.info(adapterDescription + " :: timestamp added with value :: " + formattedDateTime);
//Set the transactionId header
UUID uuid = java.util.UUID.randomUUID();
serviceUrlConnection.setRequestProperty("transactionId", uuid.toString());
logger.info(adapterDescription + " :: transactionID added with value :: " + uuid.toString());
//Set the sourceSystem header
String sourceSystem = + InetAddress.getLocalHost().getHostName();
serviceUrlConnection.setRequestProperty("sourceSystem", sourceSystem);
logger.info(adapterDescription + " :: sourceSystem added with value :: " + sourceSystem);
int responseCode;
serviceUrlConnection.setDoOutput(true);
wr = new DataOutputStream(serviceUrlConnection.getOutputStream());
wr.writeBytes("");
logger.info(adapterDescription +" :: " + wr);
responseCode = serviceUrlConnection.getResponseCode();
logger.info(adapterDescription +":: responseCode :: " + responseCode);
is = serviceUrlConnection.getInputStream();

Error 400 means that there's something wrong with your request. A few things to check:
Is the server really expecting a GET request, not a POST? To do a post you can call serviceUrlConnection.setRequestMethod("POST")
You are settings setDoOutput(true) but are not writing anything in the request. Maybe you need to write some content.

By default the request method is GET. So, If no data need to be sent over, we dont need to set the DataOutputStream and also no need to call setDoOutput(true)
/*
Commented out the below lines:-
wr = new DataOutputStream(serviceUrlConnection.getOutputStream());
serviceUrlConnection.setDoOutput(true);
*/
See an exiting SO question :-
HttpURLConnection sends a POST request even though httpCon.setRequestMethod("GET"); is set

Related

Can you please advise How to mock the Rest Template

Is there any possibility to write the mockito condition on it. if not let me know how to change the actual code.
String url = new StringBuilder(EPARTNER_MICRO_SERVICE_URL).append(service).toString();
RequestEntity<String> requestEntity = new RequestEntity<String>(prePreocess(ePartnerRestRequestDTO), HttpMethod.POST, new URI(url));
Instant before = Instant.now();
ResponseEntity<String> response = new RestTemplate().exchange(requestEntity, String.class);
logger.info("ePartner service " + url + " - duration (milliseconds) :: " + Duration.between(before, Instant.now()).toMillis());
if(isObjectPresent(response) && isObjectPresent(response.getStatusCode()) && HttpStatus.OK == response.getStatusCode()) {
ePartnerRestResponseDTO = postProcess(JWSResponseUtil.verifyJWSSignatureAndExtractPayload(response.getBody()));

How to? - Insert a string into a php file before the same file does a GET

I have successfully connected my android app to a mysql database and did a read from the database which is displaying all the rows from a table in the app. I want to narrow this down so it only displays the rows which correspond with the users id. I have the usersID stored as a shared preference from when they log into the app. I need my php file to recognise the users id and then use this id as part of the query so it only displays the appropriate rows.I am having trouble trying to set this code up and would benefit from some help. Please see the php and java below.
PHP CODE:
<?php
include('conn.php');
if(isset($_GET['userId'])){//The PHP file doesnt work with these two lines
$getId = $_GET['userId'];
$query = "SELECT * FROM Cbt WHERE userId = '$getId'";
$result = mysqli_query($conn, $query);
$json_array = array();
while ($row = mysqli_fetch_assoc($result)){
$json_array[] =$row;
}
}
echo json_encode($json_array);
JAVA CODE:
loginPref = getSharedPreferences("loginPref", Context.MODE_PRIVATE);
final int userId = loginPref.getInt("userId", 0);
textViewResult = findViewById(R.id.text_viewer_result);
Gson gson = new GsonBuilder()
.setLenient()
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("")
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
Api api = retrofit.create(Api.class);
Call<List<WorkoutLogRecycler>> call = api.getLogs();
call.enqueue(new Callback<List<WorkoutLogRecycler>>() {
#Override
public void onResponse(Call<List<WorkoutLogRecycler>> call, Response<List<WorkoutLogRecycler>> response) {
if (!response.isSuccessful()) {
textViewResult.setText("Code:"+response.code());
return;
}
List<WorkoutLogRecycler> workoutLogRecyclers = response.body();
for (WorkoutLogRecycler workoutLogRecycler : workoutLogRecyclers){
String content ="";
content += "cbtId: " + workoutLogRecycler.getCbtId() +"\n";
content += "userId: " + workoutLogRecycler.getUserId() +"\n";
content += "moodBefore: " + workoutLogRecycler.getMoodBefore() +"\n";
content += "automaticThought: " + workoutLogRecycler.getAutomaticThought() +"\n";
content += "distortions: " + workoutLogRecycler.getDistortions() +"\n";
content += "challengeTought: " + workoutLogRecycler.getChallengeThought() +"\n";
content += "alternativeThought: " + workoutLogRecycler.getAlternativeThought() +"\n";
content += "moodAfter: " + workoutLogRecycler.getMoodAfter() +"\n";
textViewResult.append(content);
}
}
#Override
public void onFailure(Call<List<WorkoutLogRecycler>> call, Throwable t) {
textViewResult.setText(t.getMessage());
}
});
API CODE:
public interface Api {
#FormUrlEncoded
#POST("insert.php")
Call<ResponseBody> insertLog(
#Field("userId") int userId,
#Field("moodBefore") int moodBefore,
#Field("automaticThought") String automaticThought,
#Field("distortions") int distortions,
#Field("challengeThought") String challengeThought,
#Field("alternativeThought") String alternativeThought,
#Field("moodAfter") int moodAfter
);
#GET("read.php")
Call<List<WorkoutLogRecycler>> getLogs();
Ok so your API url getLogs() needs a parameter that will be passed to the php script
#GET("read.php")
Call<List<WorkoutLogRecycler>> getLogs(#Query("userId") String userId);
and then change the line
Call<List<WorkoutLogRecycler>> call = api.getLogs();
// to
Call<List<WorkoutLogRecycler>> call = api.getLogs(userId);
Check if it works. Basically you execute a request that is provided in the .baseUrl() but you don't attach any param to it. When you use GET on the server side, the url should contain some data attached. Like: https://www.api.com?userId=2.
Then $_GET['userId'] can extract userId value from the url.
Retrofit attach params for you using #Query adnotation.
From a first PHP sight, I can tell that you are not passing the $getId correctly within your query. What you should do is: $query = "SELECT * FROM Cbt WHERE userId = " . $getId;
Besides that, check this way of using mysqli queries by assigning them a variable.

How to make CSV file as stream from ResultSet in Java?

I am making an ajax request to an endpoint to make CSV file from ResultSet. I am doing below code to do that.
val statement = dbCon.createStatement()
val rs = statement.executeQuery(exportQuery)
val csvWriter = new PrintWriter(new File("D:\\wdd.csv"))
val meta: ResultSetMetaData = rs.getMetaData()
val numberOfColumns = meta.getColumnCount()
var dataHeaders = "\"" + meta.getColumnLabel(1) + "\""
for (i <- 2 to numberOfColumns) {
dataHeaders += ",\"" + meta.getColumnLabel(i) + "\""
}
csvWriter.println(dataHeaders)
while (rs.next()) {
var row = "\"" + rs.getString(1) + "\""
for (i <- 2 to numberOfColumns) {
row += ",\"" + rs.getString(i) + "\""
}
csvWriter.println(row)
}
csvWriter.close()
But the problem is that it is actually writing to a file in the server side. I don't want that to write a file in the server side instead i what i want is that when client will fire this endpoint, the file will automatically be downloaded in the client side.
This is my Ajax request.
exportDataAsCSVFile: function (schemaName, params) {
var deferred = can.Deferred();
$.ajax({
url: '/adhoc-matching/export-csv/' + schemaName,
type: 'POST',
contentType: "application/json",
dataType: 'json',
async: true,
data: JSON.stringify(params),
success: function (data) {
deferred.resolve(data);
},
error: function (xhr, settings, exception) {
deferred.reject(xhr, settings, exception);
}
});
return deferred.promise();
}
How can i make CSV in memory as stream and send the stream to the client to automatically download as a file??
I am using Scala Ok(write(resp)) to send the response. What needs to be changed to the request headers to send the stream?
EDIT:
I could make the stream into an string. But what should i write in the ajax request to download the file in client side. I have tried to give dataType as "text/csv" or "text" and also added below headers.
$.ajax({
headers: {
Accept : "text/csv; charset=utf-8",
"Content-Type": "text/csv; charset=utf-8"
}
But the file is not downloading in the client side though the response has the text. Below what i tried out to make CSV:
val csvWriter: StringWriter = new StringWriter
try {
val statement = dbCon.createStatement()
val rs = statement.executeQuery(exportQuery)
val meta: ResultSetMetaData = rs.getMetaData()
val numberOfColumns = meta.getColumnCount()
var dataHeaders = "\"" + meta.getColumnLabel(1) + "\""
for (i <- 2 to numberOfColumns) {
dataHeaders += ",\"" + meta.getColumnLabel(i) + "\""
}
csvWriter.write(dataHeaders + "\n")
while (rs.next()) {
var row = "\"" + rs.getString(1) + "\""
for (i <- 2 to numberOfColumns) {
row += ",\"" + rs.getString(i) + "\""
}
csvWriter.write(row + "\n")
//csvWriter.println(row)
}
csvWriter.flush()
}
catch {
case e: Exception =>
}
finally {
dbCon.close()
csvWriter.close()
}
val fileName = "untitled.csv"
val csvData = csvWriter.toString
Ok(csvData).as("text/csv; charset=utf-8").withHeaders(
CONTENT_DISPOSITION -> s"attachment; filename=$fileName",
CONTENT_LENGTH -> csvData.length.toString
)
Your server side code should look like this:
#RequestMapping(method = RequestMethod.GET, value = "csv",
produces = { AdditionalMediaTypes.TEXT_CSV_UTF8, AdditionalMediaTypes.APPLICATION_CSV_UTF8 })
public void getCsvFile(HttpServletRequest request, HttpServletResponse response) throws Exception {
csvWriter.writeCsvToResponse(request, response);
}
When called a csv file would download to the client.
public void writeCsvToResponse(HttpServletRequest request,
HttpServletResponse response) throws IOException {
methodToWriteYourThingAsCsv.writeToStream(yourListOfObjectsYouWantToWrite, response.getOutputStream());
}

Request header is returning NULL

I have some issue with the code below, req.getHeader() is returning NULL
// The code below returns the expected value
String header = req.getHeader("x-key");
String size = req.getHeader("x-size");
String contentType = req.getContentType();
logger.info("Content-Length: " + req.getContentLength());
logger.info("x-key : " + header);
logger.info("x-size : " + size);
// The value of req.getHeader below is returning NULL
for (Enumeration e = req.getHeaderNames(); e.hasMoreElements();) {
String headerName = (String) e.nextElement();
logger.info("Name = " + headerName + " " + "Value = " + req.getHeader(headerName ));
}
What could be the problem?
Your code looks OK. If getHeader() returns null the header is indeed null, i.e. was not sent by client.
So, first check your client and be sure it sends the header. Second, try to use network sniffer, e.g. Wireshark and record the network activity.
If you need more assistance please post your client's code.
The below is part of the extract from the api docs.
public java.util.Enumeration getHeaderNames()
Some servlet containers do not allow servlets to access headers using this method, in which case this method returns null

Returning JSON response from Servlet to Javascript/JSP page

I think (actually I KNOW!) I'm doing something wrong here I am trying to populate some values into HashMap and add each hasmap to a list which will be added to a JSON object:
JSONObject json = new JSONObject();
try
{
Map address;
List addresses = new ArrayList();
int count = 15;
for (int i=0 ; i<count ; i++)
{
address = new HashMap();
address.put("CustomerName" , "Decepticons" + i);
address.put("AccountId" , "1999" + i);
address.put("SiteId" , "1888" + i);
address.put("Number" , "7" + i);
address.put("Building" , "StarScream Skyscraper" + i);
address.put("Street" , "Devestator Avenue" + i);
address.put("City" , "Megatron City" + i);
address.put("ZipCode" , "ZZ00 XX1" + i);
address.put("Country" , "CyberTron" + i);
addresses.add(address);
}
json.put("Addresses", addresses);
}
catch (JSONException jse)
{
}
response.setContentType("application/json");
response.getWriter().write(json.toString());
My problem is I know this is returning a string, which I cannot seem to parse (which is the problem). My question is how do I return the actual JSON encoded string (or even should I be doing this?) or what is the best method of attack for this type of problem. The JavaScript I am using for this is below:
function getReadyStateHandler(req)
{
// Return an anonymous function that listens to the
// XMLHttpRequest instance
return function ()
{
// If the request's status is "complete"
if (req.readyState == 4)
{
// Check that a successful server response was received
if (req.status == 200)
{
msgBox("JSON Response recieved...");
populateDatagrid(req.responseText.toJSON());
}
else
{
// An HTTP problem has occurred
alert("HTTP error: " + req.status);
}
}
}
}
Note the JSON Response comes back fine, but its a string. Any advice is greatly appreciated. I am also opening to using googles Gson, but don't have too much knowledge on that.
Got it working! I should have been building a JSONArray of JSONObjects and then add the array to a final "Addresses" JSONObject. Observe the following:
JSONObject json = new JSONObject();
JSONArray addresses = new JSONArray();
JSONObject address;
try
{
int count = 15;
for (int i=0 ; i<count ; i++)
{
address = new JSONObject();
address.put("CustomerName" , "Decepticons" + i);
address.put("AccountId" , "1999" + i);
address.put("SiteId" , "1888" + i);
address.put("Number" , "7" + i);
address.put("Building" , "StarScream Skyscraper" + i);
address.put("Street" , "Devestator Avenue" + i);
address.put("City" , "Megatron City" + i);
address.put("ZipCode" , "ZZ00 XX1" + i);
address.put("Country" , "CyberTron" + i);
addresses.add(address);
}
json.put("Addresses", addresses);
}
catch (JSONException jse)
{
}
response.setContentType("application/json");
response.getWriter().write(json.toString());
This worked and returned valid and parse-able JSON. Hopefully this helps someone else in the future. Thanks for your help Marcel
I used JSONObject as shown below in Servlet.
JSONObject jsonReturn = new JSONObject();
NhAdminTree = AdminTasks.GetNeighborhoodTreeForNhAdministrator( connection, bwcon, userName);
map = new HashMap<String, String>();
map.put("Status", "Success");
map.put("FailureReason", "None");
map.put("DataElements", "2");
jsonReturn = new JSONObject();
jsonReturn.accumulate("Header", map);
List<String> list = new ArrayList<String>();
list.add(NhAdminTree);
list.add(userName);
jsonReturn.accumulate("Elements", list);
The Servlet returns this JSON object as shown below:
response.setContentType("application/json");
response.getWriter().write(jsonReturn.toString());
This Servlet is called from Browser using AngularJs as below
$scope.GetNeighborhoodTreeUsingPost = function(){
alert("Clicked GetNeighborhoodTreeUsingPost : " + $scope.userName );
$http({
method: 'POST',
url : 'http://localhost:8080/EPortal/xlEPortalService',
headers: {
'Content-Type': 'application/json'
},
data : {
'action': 64,
'userName' : $scope.userName
}
}).success(function(data, status, headers, config){
alert("DATA.header.status : " + data.Header.Status);
alert("DATA.header.FailureReason : " + data.Header.FailureReason);
alert("DATA.header.DataElements : " + data.Header.DataElements);
alert("DATA.elements : " + data.Elements);
}).error(function(data, status, headers, config) {
alert(data + " : " + status + " : " + headers + " : " + config);
});
};
This code worked and it is showing correct data in alert dialog box:
Data.header.status : Success
Data.header.FailureReason : None
Data.header.DetailElements : 2
Data.Elements : Coma seperated string values i.e. NhAdminTree, userName
I think that what you want to do is turn the JSON string back into an object when it arrives back in your XMLHttpRequest - correct?
If so, you need to eval the string to turn it into a JavaScript object - note that this can be unsafe as you're trusting that the JSON string isn't malicious and therefore executing it. Preferably you could use jQuery's parseJSON

Categories

Resources