How to make CSV file as stream from ResultSet in Java? - 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());
}

Related

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.

java object to json object to javascript object

I am trying to implement the jQuery autocomplete custom data and display. Right now I'm using just the regular autocomplete. My problem is converting the json array of json objects to an array of javascript objects. Could someone please point me in the right direction. Here is what I currently have for the standard autocomplete.
javascript:
$('input[type=radio][name=transaction]').change(function(){
console.log($('input[type=radio][name=transaction]:checked').val());
$.ajax({
type: "post",
async: false,
url: "/autocomplete",
contenttype: "application/json; charset=utf-8",
datatype: "json",
data: "transaction="+$('input[type=radio][name=transaction]:checked').val(),
success: function (data)
{
if($('input[type=radio][name=transaction]:checked').val() == "sell")
{
theSymbols = JSON.parse(data);
}
else
{
theSymbols = data;
}
},
error: function (bad)
{
alert("Autocomplete failed.");
}
});
if($('input[type=radio][name=transaction]:checked').val() == "sell")
{
$("#symbol").autocomplete(
{
minLength: 0,
source: theSymbols,
focus: function(event, ui) {
$("#symbol").val(ui.item.value);
return false;
},
select: function(event, ui)
{
$("#symbol").val( ui.item.value);
$("#sharesOwn").html( ui.item.shares);
$("#sharesText").show();
return false;
}
})
.autocomplete("instance")._renderItem = function(ul, item)
{
return $("<li>")
.append("<a>" + item.label + "<br><span class='acFormat'>" + item.desc + "</span></a>")
.appendTo(ul);
};
}
else
{
$("#symbol").autocomplete({source: theSymbols});
}
java:
ArrayList<String> symbols = new ArrayList<String>();
ArrayList<Position> positionList = new ArrayList<Position>();
positionList = PositionDB.getPositions(user.getPortfolioID(), "O");
for (Position p : positionList)
{
String data = "";
data = "{";
data += "value: " + p.getSymbol();
data += ", label: " + p.getSymbol();
data += ", desc: " + p.getCompName();
data += ", shares: " + p.getShares();
data += "}";
symbols.add(data);
}
Gson gson = new Gson();
JsonElement syms = gson.toJsonTree(symbols, new TypeToken<List<String>>() {}.getType());
response.setContentType("application/json; charset=UTF-8");
JsonArray jArray = syms.getAsJsonArray();
PrintWriter out = response.getWriter();
System.out.println(jArray);
out.print(jArray);
out.flush();
Stock object has symbol, company name and price.
I'm having problems creating the JSON array or objects to pass to my javascript. Right now it outputs as if it were a js array of objects but keys are showing up in the textbox, along with the values so the autocomplete must be seeing it as a string, which means that I can't build it as a string in java so I need a different way. Ideas?
Thank you.

Making an AJAX POST on websocket message is causing timeout exceptions

So I have a program that basically allows two users two chat back and forth and do other things via websocket with javascript and java server endpoints. When one of the users presses a button I have a listener that fires off a message to the other user which invokes a function. During this function I want to be able to call an AJAX POST with JQuery to update my database but this is causing a java.util.concurrent.TimeoutException. Any idea why this occurs? I imagine it has something to do with the fact that the websocket connection doesn't stay open long enough for the ajax call to go through.
So I've done the research and I've seen that websocket and AJAX are not exactly something that should be mixed (I think). However I can't seem to figure out an alternative even to update my database. There is a lot of code for this so I will try and only post the important parts.
Here is the part of the code for when the button is pressed (it is an agree button so both users must have pressed it hence the '**' and '--' characters).
fAgree.addEventListener("click", function() {
// selects this button
if (aStr == "**" && (yStr == "**" || oStr == "**")) {
if (fStr == "--") {
fStr = "*-";
//redirect to another page
} else if (fStr == "-*") {
fStr = "**";
if(secondTransaction == false) {
var firstCoordUpload = document.getElementById("yourPos").innerHTML;
var secondCoordUpload = document.getElementById("othersPos").innerHTML;
var firstLatUpload = parseFloat(firstCoordUpload.split(",")[0]);
var firstLonUpload = parseFloat(firstCoordUpload.split(",")[1]);
$.ajax({
url: "../../309/T11/setSaleData/" + getURLParameter("saleID") + "/" + firstLatUpload + "/" + firstLonUpload + "/" + firstCoordUpload + "/" + secondCoordUpload + "/" + secondSeller,
type: "POST",
headers: {
"Authorization" : getCredentials(),
},
success: function (result) {
window.location.href = '../../frontEnd/profilePage/index.html?username='+ getUsername();
console.log(result);
},
error: function (dc, status, err) {
console.log(err);
console.log(status);
}
});
}
}
agreeBut.socket.send("a,f");
htmlChange(fStr, fStar);
}
});
Here is the part of the code that is called at the end of the code above (the agreeBut.socket.send()).
agreeBut.socket.onmessage = function(message) {
// check [0]: a for agree buttons,
// m for map,
// l of location buttons,
// t for trade
var mess = message.data.split(",");
if (mess[0] == "a") {
// second a shows the agree button was pressed, changes aStr
// accordingly and displays
if (mess[1] == "a") {
if (aStr == "--") {
aStr = "-*";
} else if (aStr == "*-") {
aStr = "**";
}
htmlChange(aStr, aStar);
// shows the final agree button has been pressed, changes fStr
// accordingly and displays
} else if (mess[1] == "f") {
if (fStr == "--") {
fStr = "-*";
//redirect
} else if (fStr == "*-") {
fStr = "**";
alert("on this");
if(secondTransaction == true) {
alert("doing it");
var firstCoordUpload = document.getElementById("yourPos").innerHTML;
var secondCoordUpload = document.getElementById("othersPos").innerHTML;
var firstLatUpload = parseFloat(firstCoordUpload.split(",")[0]);
var firstLonUpload = parseFloat(firstCoordUpload.split(",")[1]);
$.ajax({
url: "../../309/T11/setSaleData/" + getURLParameter("saleID") + "/" + firstLatUpload + "/" + firstLonUpload + "/" + firstCoordUpload + "/" + secondCoordUpload + "/" + secondSeller,
type: "POST",
headers: {
"Authorization" : getCredentials(),
},
success: function (result) {
console.log(result);
alert("Got it");
window.location.href = '../../frontEnd/profilePage/index.html?username='+ getUsername();
},
error: function (dc, status, err) {
console.log(err);
console.log(status);
}
});
}
//window.location.href = '../../frontEnd/profilePage/index.html?username='+ getUsername();
}
htmlChange(fStr, fStar);
}
}
};
It turns out I was getting this problem because of the timeout that was set on my java ServerEndpoint. In the class I used the setMaxIdleTimeout(0) function on the session variable to have no idle timeout. This seemed to solve my problem (however I feel like this is really just a workaround for poor websocket and ajax implementation on my end).

Manage ArrayList in jquery and print exit in jsp

what i wanted to do is use jquery to get data from the databases and show it in the jsp pages.
In my jsp:
<input onclick="getPlatform('${item.string1}')"type="radio" id="${item.string1}" name="tab-group-1" checked>
in my .js:
$.ajax({
type: "POST",
url: "Controller?operation=GetPlatforms",
data: dataString,
dataType: "json",
//if received a response from the server
success: function(data, textStatus, jqXHR) {
//our platform was correct so we have some information to display
if (data.success) {
$.each(data.PlatformInfo, function() {
$("#ajaxResponsePlatforms").html("");
$("#ajaxResponsePlatforms").append("value: " + data.PlatformInfo.name);
});
}
//display error message
else {
$("#ajaxResponsePlatforms").html("<div><b>Country code is Invalid!</b></div>");
}
},
the server output is:
value of JsonElement: [{"name":"PC"},{"name":"Servers"}]
value of myObj: {"success":true,"PlatformInfo":[{"name":"PC"},{"name":"Servers"}]}
and the result in my JSP pages is:
value: undefined
Code to build Json response:
String technology = request.getParameter("technology");
System.out.println("Test " + technology);
PrintWriter out = response.getWriter();
response.setContentType("text/html");
response.setHeader("Cache-control", "no-cache, no-store");
response.setHeader("Pragma", "no-cache");
response.setHeader("Expires", "-1");
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST");
response.setHeader("Access-Control-Allow-Headers", "Content-Type");
response.setHeader("Access-Control-Max-Age", "86400");
Gson gson = new Gson();
JsonObject myObj = new JsonObject();
BACENGQueryDatabases PlatformData = new BACENGQueryDatabases();
ArrayList PlatformInfo = PlatformData.GetPlatform(technology);
JsonElement platformObj = gson.toJsonTree(PlatformInfo);
System.out.println("JsonElement: " + platformObj);
if (PlatformInfo.isEmpty()) {
myObj.addProperty("success", false);
System.out.println("Array empty");
} else {
myObj.addProperty("success", true);
System.out.println("Array full");
}
System.out.println("value json " + platformObj);
myObj.add("PlatformInfo", platformObj);
out.println(myObj.toString());
System.out.println(" myObj: " + myObj.toString());
out.close();
It's happenign since I want to do get the result as ArraList form, however if instead Array I use a single String object it is working fine.
how can use ArayList and jquery.apped method?
if you use $.each on data.PlatformInfo you shoud use what's iterated on inside the callback, not data.PlatformInfo which is a list (and has no .name), something like this:
$.each(data.PlatformInfo, function(i, e) { // i = index, e = element
// are you sure you want to: $("#ajaxResponsePlatforms").html("");
$("#ajaxResponsePlatforms").append("value: " + e.name);
});
Also note that setting html content to "" inside the loop is probably not what you want, you probably want that before the $.each.
Demo: JSFiddle

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