error javax.net.ssl.SSLHandshakeException: - java

I need really your support.
I have a big problem that I don't understand why happens.
I used https-nativescript plugin because I want to communicate with protocol https.
So, Firstly I install this plugin, and write in component.ts this code:
enableSSLpinning() {
let certificate: any;
Https.enableSSLPinning({ host: 'xx.xxx.xx.xx:3333', certificate, allowInvalidCertificates: true, validatesDomainName: false })
Https.request({
url: 'https://xx.xxx.xx.xx:3333/user',
method: 'GET',
headers: {
"Content-type": "application/x-www-form-urlencoded",
},
}).then(function (response) {
console.log('Https.request response', response);
}).catch(function (error) {
console.error('Https.request error', error);
})
}
in https.android.js I modify only certificate in this part:
function enableSSLPinning(options) {
if (!peer.host && !peer.certificate
) {
var certificate = void 0;
var InputSteram = void 0;
try {
var inputStream = new java.io.ByteArrayInputStream(new java.lang.String("-----BEGIN CERTIFICATE-----\n"
+ "MIIFjDCCA3SgAwIBAgIJAMOXpEn+QQSVMA0GCSqGSIb3DQEBCwUAMIGBMQswCQYD\n"
+ "VQQGEwJVUzELMAkGA1UECAwCTUExDzANBgNVBAcMBkJvc3RvbjETMBEGA1UECgwK\n"
..................
+ "1AYJwo2yFqmetdmOYaFh6Cli8OerUERDqPB1UKPmYQE=\n"
+ "-----END CERTIFICATE-----").getBytes("UTF-8"));
var x509Certificate = java.security.cert.CertificateFactory.getInstance('X.509').generateCertificate(inputStream);
peer.x509Certificate = x509Certificate;
certificate = okhttp3.CertificatePinner.pin(x509Certificate);
inputStream.close();
}
catch (error) {
try {
if (inputStream) {
console.log('inputStream', inputStream)
inputStream.close();
}
}
catch (e) { }
console.error('nativescript-https > enableSSLPinning error', error);
return;
}
peer.host = options.host;
peer.certificate = certificate;
if (options.allowInvalidCertificates == true) {
peer.allowInvalidCertificates = true;
}
if (options.validatesDomainName == false) {
peer.validatesDomainName = false;
}
}
peer.enabled = true;
getClient(true);
console.log('nativescript-https > Enabled SSL pinning');
}
This parts execute correct, in console print 'nativescript-https > Enabled SSL pinning'
Error show in this part: console.error('Https.request error', error);
JS: Https.request error javax.net.ssl.SSLHandshakeException:
java.security.cert.CertPathValidatorException: Trust anchor for
certification path not found.
And in https.android.js call this function
function request(opts) {
console.log('opts', opts)
return new Promise(function (resolve, reject) {
try {
var client = getClient();
var request_1 = new okhttp3.Request.Builder();
request_1.url(opts.url);
var reqheads_1 = opts.headers;
Object.keys(reqheads_1).forEach(function (key) {
request_1.addHeader(key, reqheads_1[key]);
});
if (opts.method == 'GET') {
request_1.get();
}
else if (opts.method == 'POST') {
var type = okhttp3.MediaType.parse('application/json');
var body = okhttp3.RequestBody.create(type, opts.content);
request_1.post(body);
}
client.newCall(request_1.build()).enqueue(new okhttp3.Callback({
onResponse: function (task, response) {
var content;
try {
content = JSON.parse(response.body().string());
}
catch (error) {
return reject(error);
}
var statusCode = response.code();
var headers = {};
var heads = response.headers();
var i, len = heads.size();
for (i = 0; i < len; i++) {
var key = heads.name(i);
var value = heads.value(i);
headers[key] = value;
}
resolve({ content: content, statusCode: statusCode, headers: headers });
},
onFailure: function (task, error) {
reject(error);
},
}));
}
catch (error) {
reject(error);
}
});
}
Please, can you ask me any idea, which is the problem in my code? Thank you
Thanks!
Update:
I think that a problem is in this part of code:
onResponse: function (task, response) {
console.load('testfdsfsdfsdfsd')
var content;
console.log('content', content)
try {
content = JSON.parse(response.body().string());
console.log('content1', content)
}
catch (error) {
console.log('error111111', error)
return reject(error);
}
var statusCode = response.code();
var headers = {};
var heads = response.headers();
var i, len = heads.size();
for (i = 0; i < len; i++) {
var key = heads.name(i);
var value = heads.value(i);
headers[key] = value;
}
resolve({ content: content, statusCode: statusCode, headers: headers });
},
because this part is not executed, it passes directly to onFailure
onFailure: function (task, error) {
reject(error);
},

Related

event error :unhandled event er

var uploadLogoAdImage = function (req, res) {
var appName = req.params.appName;
var ftpEndPointPath = '${com.wowza.wms.context.VHostConfigHome}/content/';
var s3_bucket = 'w-a-images';
var uploadParams = {
Bucket: s3_bucket,
Key: '',
Body: '',
ACL: 'public-read'
};
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploadTemp/');
},
filename: function (req, file, cb) {
var datetimestamp = Date.now();
cb(null, file.originalname.split('.')[file.originalname.split('.').length - 2] + '-' + datetimestamp + '.' + file.originalname.split('.')[file.originalname.split('.').length - 1]);
}
});
var upload = multer({
storage: storage
}).single('file');
upload(req, res, function (err) {
console.log(req.file);
if (err) {
res.json({ error_code: 1, err_desc: err });
return;
}
var filePathStr = req.file.path;
var splitter = filePathStr.toString().split('\\');
var fileName = splitter[1];
var file = filePathStr;
var fileStream = fs.createReadStream(file);
var read_file = fs.readFileSync(file);
fileStream.on('error', function (err) {
console.log('File Error', err);
});
var client = new Client();
var ftpConfig = {
host: '13.126.230.30',
port: 21,
user: 'wftp',
password: 'xxxxxxxxx'
}
client.connect(ftpConfig);
uploadParams.Body = fileStream;
uploadParams.Key = 'l_ads/' + path.basename(file);
s3.upload(uploadParams, (err, data) => {
if (err) {
console.log("Error", err);
}
if (data) {
console.log(data);
}
});
client.on('ready', function () {
client.put(filePathStr, './' + fileName, function (ftpErr) {
if (ftpErr) {
console.log(ftpErr);
} else {
client.end();
res.status(200).json({
message: 'success',
videoUrl: 'https://wowstream-ads-images.s3.ap-south-1.amazonaws.com/' + uploadParams.Key,
ftpPath: ftpEndPointPath + fileName,
fileSize: req.file.size,
fileName: fileName
});
}
});
});
});
};
ERROR:
events.js:183
throw er; // Unhandled 'error' event
^
Error: connect ECONNREFUSED 13.126.230.30:21
at Object._errnoException (util.js:1022:11)
at _exceptionWithHostPort (util.js:1044:20)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1182:14)
Waiting for the debugger to disconnect...
[nodemon] app crashed - waiting for file changes before starting...
I tried all the things but still the same error.I insatll new version of fs package and iconic script both are does not work.In S3 files were upload afterthat i didn't get proper response.
i tried all those things whatever they said.I did not understand where the error throws.The data are stored in the s3 then it throw event unhandled error.Sometimes connection refused sometimes timeout error coming.
Since two days i tried all methods and i did not get any solution

CKEditor 5 upload image, What information does the upload image return?

This is web code:
DecoupledEditor
.create( document.querySelector( '#webDetails' ),{
language: 'zh-cn',
image: {
toolbar: [ 'imageTextAlternative' ],
styles: [ 'full', 'side' ]
},
ckfinder: {
uploadUrl: '<%=WEBPATH%>/platform/updateMaterial'
}
} )
.then( editor => {
const toolbarContainer = document.querySelector( '#toolbar-webDetails' );
toolbarContainer.appendChild( editor.ui.view.toolbar.element );
} )
This is Spring controller:
#PostMapping("updateMaterial")
#ResponseBody
public String updateMaterial(#RequestParam("upload") MultipartFile file, HttpServletRequest request){
String trueFileName = null;
String realPath = null;
try {
realPath = request.getSession().getServletContext().getRealPath("/upload");
System.out.println(realPath);
trueFileName = uploadImg(realPath, file);
} catch (IllegalStateException | IOException e) {
e.printStackTrace();
}
return "{\"default\":\"" + realPath + File.separator + trueFileName + "\"}";
}
Here I return the address of the image on disk.
It is json String style. I want CKEditor 5 api to return the information, but still failure.
What do I need to return in the background to succeed, or am I missing the step?
thank you.
There are many people asking this question, but none of them have a clear solution. Finally, I found it. My code is as follows.
class UploadAdapter {
constructor(loader) {
this.loader = loader;
}
upload() {
return new Promise((resolve, reject) => {
const data = new FormData();
data.append('upload', this.loader.file);
data.append('allowSize', 10);//允许图片上传的大小/兆
$.ajax({
url: 'loadImage',
type: 'POST',
data: data,
dataType: 'json',
processData: false,
contentType: false,
success: function (data) {
if (data.res) {
resolve({
default: data.url
});
} else {
reject(data.msg);
}
}
});
});
}
abort() {
}
}
DecoupledEditor
.create( document.querySelector( '#b' ), {
language:"zh-cn"
})
.then( editor => {
const toolbarContainer = document.querySelector( '#a' );
toolbarContainer.appendChild( editor.ui.view.toolbar.element );
// This place loads the adapter.
editor.plugins.get('FileRepository').createUploadAdapter = (loader)=>{
return new UploadAdapter(loader);
};
} )
.catch( error => {
console.error( error );
} );

Cant access success function when call recursive ajax

I'm building a system which has push notification feature and use Jersey to create API.
I read an article about comet approach and end up with the following code:
Index.js
function checkExamNotification() {
$.ajax({
url: contextPath + '/api/notification/checkExamNotification',
type: 'get',
data: {
accountId: accountId,
sessionId: sessionId
},
success: function (res) {
console.log("success");
displayNumberOfNotification();
checkExamNotification();
},
error: function (jqXHR, textStatus, errorThrown) {
if (textStatus === "timeout") {
checkExamNotification();
}
}
});
}
$(document).ready(function () {
$.ajaxSetup({
timeout: 1000*60*3
});
checkExamNotification();
});
Check exam notification API
#GET
#Path("/checkExamNotification")
public Response checkExamNotification(#QueryParam("accountId") int accountId, #QueryParam("sessionId") String sessionId) throws InterruptedException {
if (memCachedClient.checkSession(sessionId, accountId)) {
while (!examNotificationQueue.hasItems()) {
Thread.sleep(5000);
}
ExamNotificationQueueItemModel examNotificationQueueItemModel = examNotificationQueue.dequeue();
if (examNotificationQueueItemModel.getAccountId() == accountId) {
LOGGER.info("[START] Check exam notification API");
LOGGER.info("Account ID: " + accountId);
LOGGER.info("Get notification with exam ID: " + examNotificationQueueItemModel.getExamId());
ExamEntity exam = examDAO.findById(examNotificationQueueItemModel.getExamId());
NotificationEntity notification = notificationDAO.findByExamId(exam.getExamid());
notification.setSend(1);
notificationDAO.getEntityManager().getTransaction().begin();
notificationDAO.update(notification);
notificationDAO.getEntityManager().getTransaction().commit();
LOGGER.info("[END]");
String result = gson.toJson(examNotificationQueueItemModel);
return Response.status(200).entity(result).build();
} else {
examNotificationQueue.enqueue(examNotificationQueueItemModel);
Thread.sleep(5000);
checkExamNotification(accountId, sessionId);
}
}
return Response.status(200).entity(gson.toJson("timeout")).build();
}
From my debug, the API did finish return but the success event SOMETIMES didn't fire.
Yes, sometimes console log success but sometimes it doesn't.
Can anybody explain to me this case?
Thanks in advance. Any help would be appreciated.
Ok after following #peeskillet comment. Here is my finally code.
Check exam notification API
#GET
#Produces(SseFeature.SERVER_SENT_EVENTS)
#Path("/checkExamNotification")
public EventOutput checkExamNotification(#QueryParam("accountId") final int accountId, #QueryParam("sessionId") final String sessionId) {
final EventOutput eventOutput = new EventOutput();
if (memCachedClient.checkSession(sessionId, accountId)) {
new Thread(new Runnable() {
public void run() {
try {
if (examNotificationQueue.hasItems()) {
ExamNotificationQueueItemModel examNotificationQueueItemModel = examNotificationQueue.dequeue();
if (examNotificationQueueItemModel.getAccountId() == accountId) {
LOGGER.info("[START] Check exam notification API");
LOGGER.info("Account ID: " + accountId);
LOGGER.info("Get notification with exam ID: " + examNotificationQueueItemModel.getExamName());
String result = gson.toJson(examNotificationQueueItemModel);
final OutboundEvent.Builder eventBuilder
= new OutboundEvent.Builder();
eventBuilder.data(result);
final OutboundEvent event = eventBuilder.build();
eventOutput.write(event);
LOGGER.info("[END]");
} else {
examNotificationQueue.enqueue(examNotificationQueueItemModel);
}
}
} catch (IOException e) {
throw new RuntimeException(
"Error when writing the event.", e);
} finally {
try {
eventOutput.close();
} catch (IOException ioClose) {
throw new RuntimeException(
"Error when closing the event output.", ioClose);
}
}
}
}).start();
}
return eventOutput;
}
Index.js
function checkExamNotification() {
var url = contextPath + '/api/notification/checkExamNotification?accountId=' + accountId + '&sessionId=' + sessionId;
var source = new EventSource(url);
source.onmessage = function (event) {
displayNumberOfNotification();
};
}

Download excel file generated with Apache Poi

I am creating an Excel file with Apache Poi and then downloading it. My problem is that when i try to open the file i get the error:
The file you are trying to open, 'workbook.xls', is in a different
format than specified by the file extension. Verify that the file is
not corrupted and is from a trusted source before opening the file. Do
you want to open the file now?
and when i click yes, the downloaded file has strange characters and is not formatted correctly.
If i save the file, instead of download it, it is generated correctly.
Here is my code:
Calling the servlet from angular:
NetWorkModel.sendRequestOpiniumServlet("review", metodoPeticion, dataEntrada, "EXCEL", function (response) {
if (response.Status === 'KO') {
NotificacionModel.mostrarNotificacion({
title: 'Opinium',
message: 'Error. No se ha podido exportar a Excel.',
size: 'large',//small,large
type: 'error',//error,notice,warning
duration: '2000'
});
}
callback();
});
sendRequestOpiniumServlet method in netWorkModel.js:
this.sendRequestOpiniumServlet = function (servicioPeticion, metodoPeticion, dataEntrada, tipoPeticion, callback, $files) {
//Reset de la request y ponemos los valores del ususario
self.resetValue();
//Ponemos datos de la peticion
self.request.Servicio = servicioPeticion;
self.request.Metodo = metodoPeticion;
self.request.Entrada = dataEntrada;
var tipo = "";
if (tipoPeticion === "JSON") {
tipo = "";
self.request.Tipo = tipo;
self.sendHttpJSON(self.servers.urlOpinium, function (data) {
callback(data);
});
} else if (tipoPeticion === "EXCEL") {
tipo = "EXCEL";
self.request.Tipo = tipo;
self.sendHttpExcel(self.servers.urlOpinium, function (data) {
callback(data);
});
} else if (tipoPeticion === "CSV") {
tipo = "CSV";
self.request.Tipo = tipo;
var nombreCSV = servicioPeticion;
self.sendHttpCSV(nombreCSV, self.servers.urlOpinium, function (data) {
callback(data);
});
} else if (tipoPeticion === "IMG") {
tipo = "IMG";
self.request.Tipo = tipo;
self.sendHttpIMG(self.servers.urlOpinium, $files, function (data) {
callback(data);
});
}
};
sendHttpExcel method in netWorkModel.js:
this.sendHttpExcel = function (urlService, callback) {
$http({
method: self.servers.method, url: urlService,
data: JSON.stringify(self.request),
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
}).success(function (data, status, headers, cfg) {
if (DescargaExcelModel.createExcel('bookwork', data)) {
NotificacionModel.mostrarNotificacion({
title: 'Intranet: Exportación',
message: 'Fichero exportado correctamente',
size: 'large', //small,large
type: 'notice', //error,notice,warning
duration: '5000'
});
callback(true);
} else {
NotificacionModel.mostrarNotificacion({
title: 'Intranet: Exportación',
message: 'Error en el contenido del fichero',
size: 'large', //small,large
type: 'error', //error,notice,warning
duration: '5000'
});
callback(false);
}
}).error(function (data, status, headers, cfg) {
NotificacionModel.mostrarNotificacion({
title: 'Servidor: ' + urlService,
message: 'Error en la conexión con el servidor',
size: 'xlarge', //small,large,xlarge
type: 'error', //error,notice,warning
duration: '5000'
});
callback(false);
});
};
createExcel method in DescargaExcelModel.js:
angular.module("app.utils").service("DescargaExcelModel", ['$timeout', function($timeout) {
var self = this;
this.element = angular.element( '#link_exportar_file_csv_temp' );
this.setElement = function(elem) {
self.element = elem;
};
this.excelToURL = function(content) {
var blob;
blob = new Blob(["\ufeff",content], {type: 'application/vnd.ms-excel;charset=UTF-8',encoding:"UTF-8"});
return (window.URL || window.webkitURL).createObjectURL(blob);
};
this.sanitizeExcelName = function(name) {
if (/^[A-Za-z0-9]+\.xls$/.test(name)) {
return name;
}
if (/^[A-Za-z0-9]+/.test(name)) {
return name + ".xls";
} else {
return "file.xls";
}
};
this.revoke = function(url) {
return (window.URL || window.webkitURL).revokeObjectURL(url);
};
this.on = function(ele) {
var e = document.createEvent("MouseEvent");
e.initMouseEvent("click", false, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
ele.dispatchEvent(e);
};
this.createExcel = function(titleFile, dataExcel) {
var a_href, content, title, url;
content = dataExcel;
title = titleFile;
if (!(content !== null) && !(title !== null)) {
return false;
}
title = self.sanitizeExcelName(title);
url = self.excelToURL(content);
self.element.append("<a download=\"" + title + "\" href=\"" + url + "\"></a>");
a_href = self.element.find('a')[0];
self.on(a_href);
// $timeout(function() {
// self.revoke(url);
// });
//
self.element[0].removeChild(a_href);
// angular.element("#link_exportar_file_csv_temp").removeChild(a_href);
return true;
};
}]);
My servlet code:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
.
.
.
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment; filename=bookwork.xls");
ExportUtils.convertToWorkBook(request, response, respuesta.getDatos());
.
.
.
}
convertToWorkBook method in ExportUtils.java:
public static void convertToWorkBook(HttpServletRequest request, HttpServletResponse response, List<Object> data) {
OutputStream out = response.getOutputStream();
Workbook workbook = new HSSFWorkbook();
// ... Here i create my excel workbook
workbook.write(out);
workbook.close();
out.flush();
out.close();
}
What am i doing wrong?

File download/save from a Jersey rest api call using ANGULARJS . file is attached with response as "Content-Disposition"

I am new to angular .. I hava java rest api which return CSV file in response as attachment as | "Content-Disposition", "attachment; filename=" | content-type :application/octet-stream
Now when i am calling this api from AngularJS using $http i am getting response.data ="" (blank)
I am using basic authorisation for security so I have to pass Header while calling calling API so can't use link click or new window open fro CSV download.
to test when i removed authorisation and hit the url in browser then CSV file is being downloaded.so no issue at server side .
I need help at angularjs side to download CSV file from web api response as attachment.
Here is my Java API Code
public class ServiceAPI {
#GET
#Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response getFileAsCSVFile(){
byte[] file=null;
try {
ArrayList<> List=new ArrayList<>();// data retrieved from DB
if(null != List){
file=convertJsonToCSV(new Gson().toJson(List));
}
} catch (ParseException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return Response.ok(getBytes(file),MediaType.APPLICATION_OCTET_STREAM).header("Content-Disposition", "attachment; filename=" + "FileName.csv").build();
}
}
and Angular code :
app.controller('review', ['$scope', '$http', function ($scope, $http){
$scope.fromDate = new Date();
$scope.toDate = new Date();
$scope.minDate = new Date(
$scope.fromDate.getFullYear(),
$scope.fromDate.getMonth() - 2,
$scope.fromDate.getDate(),
$scope.toDate.getFullYear(),
$scope.toDate.getMonth() - 2,
$scope.toDate.getDate()
);
$scope.maxDate = new Date(
$scope.fromDate.getFullYear(),
$scope.fromDate.getMonth() - 2,
$scope.fromDate.getDate(),
$scope.toDate.getFullYear(),
$scope.toDate.getMonth() - 2,
$scope.toDate.getDate()
);
$scope.reviews = json;
function openSaveAsDialog(filename, content, mediaType) {
var blob = new Blob([content], {type: mediaType});
saveAs(blob, filename);
}
function callApi(url) {
// var dat=apiFactory.getServiceData(url);
// console.log(dat);
// apiFactory.getServiceData(url);
var responseType='arraybuffer';
var expectedMediaType='application/octet-stream';
$http.get(url, {
headers: {
accept: expectedMediaType
},
responseType:responseType,
cache: true,
transformResponse: function (data) {
var pdf;
if (data) {
pdf = new Blob([data], {
type: expectedMediaType
});
}
return {
response: pdf
};
}
}).then(function (data,status,headers) {
var filename='Preview.csv',
octetStreamMime = "application/octet-stream",
contentType;
headers = data.headers();
contentType = headers["content-type"] || octetStreamMime;
// openSaveAsDialog(filename, response.data, expectedMediaType);
if (navigator.msSaveBlob) {
var blob = new Blob([data], { type: contentType });
navigator.msSaveBlob(blob, filename);
} else {
var urlCreator = window.URL || window.webkitURL || window.mozURL || window.msURL;
if (urlCreator) {
// Try to use a download link
var link = document.createElement("a");
if ("download" in link) {
// Prepare a blob URL
var blob = new Blob([data.data], { type: contentType });
var url = urlCreator.createObjectURL(blob);
link.setAttribute("href", url);
link.setAttribute("download", filename);
// Simulate clicking the download link
var event = document.createEvent('MouseEvents');
event.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
link.dispatchEvent(event);
} else {
// Prepare a blob URL
// Use application/octet-stream when using window.location to force download
var blob = new Blob([data], { type: octetStreamMime });
var url = urlCreator.createObjectURL(blob);
$window.location = url;
}
}
}
});
};
$scope.submit = function (fromDate, toDate) {
$scope.url = API_url;
var resp =callApi(($scope.url).split(" ").join("%20"));
console.log(resp);
};
},
]);
I have an example with spring MVC instead of JAX-RS (Jersey)
HTML:
<button ng-click="downloadPdf()" class="btn btn-primary">download PDF</button>
Angularjs controler:
$scope.downloadCsv = function () {
console.log("downloadCsv");
var fileName = "test.csv";
var a = document.createElement("a");
document.body.appendChild(a);
XxxxxxServiceCSV.downloadCsv().then(function (result) {
console.log("downloadCsv callback");
var file = new Blob([result.data], {type: 'application/csv'});
var fileURL = URL.createObjectURL(file);
a.href = fileURL;
a.download = fileName;
a.click();
});
};
Angularjs services:
angular.module('xxxxxxxxApp')
.factory('XxxxxxServiceCSV', function ($http) {
return {
downloadCsv: function () {
return $http.get('api/downloadCSV', { responseType: 'arraybuffer' }).then(function (response) {
return response;
});
}
};
});
Java code JAX-RS(spring MVC):
#RequestMapping(value = "/downloadCSV", method = RequestMethod.GET, produces = "application/csv")
public void demo(HttpServletResponse response) throws IOException {
List<String> names = new ArrayList<String>();
names.add("First Name");
names.add("Second Name");
names.add("Third Name");
names.add("Fourth Name");
BufferedWriter writer = new BufferedWriter(response.getWriter());
try {
response.setHeader("Content-Disposition", "attachment; filename=\"test.csv\"");
for (String name : names) {
writer.write(name);
writer.write(",");
}
writer.newLine();
} catch (IOException ex) {
} finally {
writer.flush();
writer.close();
}
}

Categories

Resources