Java: leaving the recursive method call and the loop - java

I have a service to get the validator content as a string after passing the validator id (name). The validator's XSL files are placed in the src/main/resources. I am scanning the validator directory in the src/main/resources/de/validators to check if the file is a vailable. I am converting its input to a string and returning it as result fot the service.
In the findFile() method I want to leave the recursive call and the loop after finding the match. Is that possiable in my case?
Currently I am assigning the match to the fileName class attribute which works for me. A better approach would be to break the recursive call if it is possiable in my case.
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Paths;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import de.validate.exception.ApiRequestException;
#RequestMapping("/api/v1/validators")
#RestController
public class ValidateService {
private String fileName = "";
static private Logger LOGGER = Logger.getLogger(ValidateService.class.getName());
final static private String VALIDATOR_CONFIGURATION_DIRECTORY = "de" + File.separator + "validator" + File.separator;
final static private String VALIDATOR_TYPE = ".xsl";
final static private String VALIDATOR = "validator";
#GetMapping(path = "{id}", produces = MediaType.APPLICATION_XML_VALUE)
public String getValidator(#PathVariable String id) throws Exception {
URL resource = this.getClass().getClassLoader().getResource(VALIDATOR_CONFIGURATION_DIRECTORY);
File validatorDirectory = Paths.get(resource.toURI()).toFile();
String foundId = this.findFile(id + VALIDATOR_TYPE, validatorDirectory);
String fileNameTemp = VALIDATOR_CONFIGURATION_DIRECTORY + foundId;
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(fileNameTemp);
if (inputStream == null) {
throw new ApiRequestException("Validator id is not availabe!");
}
String result = new BufferedReader(new InputStreamReader(inputStream)).lines()
.collect(Collectors.joining("\n"));
LOGGER.info("---> result: " + result);
return result;
}
public String findFile(String name, File file) {
File[] list = file.listFiles();
if (list != null)
for (File fileTemp : list) {
if (fileTemp.isDirectory()) {
this.findFile(name, fileTemp);
} else if (name.equalsIgnoreCase(fileTemp.getName())) {
//Is it possible to break the loop here and the recursive invoke?
if (fileTemp.getParentFile().getName().equals(VALIDATOR)) {
fileName = name;
} else {
fileName = fileTemp.getParentFile().getName() + File.separator + name;
}
}
}
return fileName;
}
}

Related

Scraping the main content only of a web page by JSoup and save to file

I want to scrape the main content only of a web page by JSoup and save to a file.
Test web page:
https://netbasal.com/using-the-angular-http-client-in-angular-v15-f4bec3c11926
My test program use java 11, JSoup 1.15.3.
The output is missing:
the title "Using the Angular Http Client in Angular v15",
the source codes (by Github),
the heading "Interceptors in Lazy Loaded Modules".
How to modify the test program to add the missing content?
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
public class App
{
public static void main( String[] args )
{
try {
String dir = "/home/ak/using-the-http-client-v15";
String filename = "Out";
Path path = Paths.get(dir + "/" + filename + ".txt");
Document doc = Jsoup.connect("https://netbasal.com/using-the-angular-http-client-in-angular-v15-f4bec3c11926").get();
String searchStrings[] = {
"pw-post-body-paragraph"
};
Set<String> tagNameSet = Set.of("span", "p");
List<String> output = new ArrayList<String>();
for (String searchString : searchStrings) {
Elements searchStringElements = doc.getElementsByClass(searchString);
if (searchStringElements == null)
continue;
if (searchStringElements.hasClass(searchString)) {
for (Element e : searchStringElements) {
if (tagNameSet.contains(e.tagName())) {
String str = e.wholeText() + "\n\n";
output.add(str);
}
}
}
int size = output.size();
for (int i = 0; i < size; i++) {
// Java 11 Append mode
Files.writeString(path, output.get(i),
StandardOpenOption.CREATE, StandardOpenOption.APPEND);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

read xml content from http endpoint like a map in Java

How could I get value based on a key from an XML content http enpoint, so it is something like
<authority.result result="found 7 matches" startToken="xxxxxxx">
<TestEntry keyId="0right0" test="test" valueId="rightValue123" version="1"/>
<TestEntry keyId="0wrong" test="test" valueId="0wrongValue" version="1"/>
<TestEntry keyId="0wrong0" test="test" valueId="wrong" version="1"/>
</authority.result>
I would like to get the valueId when keyId=="0right0" only, I previously wrote following but could not get value for a specific key.
URL url = new URL(endpoint);
XMLStreamReader reader = XMLInputFactory.newInstance().createXMLStreamReader(url.openStream());
String latest;
while (reader.hasNext()) {
if (reader.next() == XMLStreamConstants.START_ELEMENT) {
if (reader.getLocalName().equals("valueId")) {
latest = reader.getElementText();
return latest;
}
}
}
You need to distinguish XML element from an attribute. To read attribute name and value you have to use getAttributeName and getAttributeValue methods respectively.
Below you find example code how to read attributes:
import javax.xml.namespace.QName;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;
public class XmlStreamApp {
public static void main(String[] args) throws IOException, XMLStreamException {
...
XMLStreamReader reader = XMLInputFactory.newInstance().createXMLStreamReader(stream);
Optional<String> value = findValueForTestEntry(reader, "0right0");
System.out.println(value);
}
private static Optional<String> findValueForTestEntry(XMLStreamReader reader, String keyValue) throws XMLStreamException {
while (reader.hasNext()) {
if (reader.next() == XMLStreamConstants.START_ELEMENT) {
String localName = reader.getLocalName();
if ("TestEntry".equals(localName)) {
Optional<String> optionalValue = getValueForKey(reader, keyValue);
if (optionalValue.isPresent()) {
return optionalValue;
}
}
}
}
return Optional.empty();
}
private static Optional<String> getValueForKey(XMLStreamReader reader, String keyValue) {
String value = "";
boolean found = false;
for (int attr = reader.getAttributeCount() - 1; attr >= 0; attr--) {
QName attributeName = reader.getAttributeName(attr);
if (attributeName.getLocalPart().equals("keyId")) {
found = keyValue.equals(reader.getAttributeValue(attr));
}
if (attributeName.getLocalPart().equals("valueId")) {
value = reader.getAttributeValue(attr);
}
}
return found ? Optional.of(value) : Optional.empty();
}
}
Above code prints:
Optional[rightValue123]
You could use an xpath to get to the desired value :
string(//TestEntry[#keyId="0right0"]/#valueId)

email receives duplicates from SPRING JAVA Mail APIs

I use Java mail APIs from a spring web application to send a weekly email to an outlook mail.
The feature was behaving normally for the first couple of weeks, then without any changes outlook received two emails, the next week three emails were received, then four, then five emails.
The logs set in the Java code indicates that only one email is being sent from the application.
I can't replicate the issue by changing the schedule to send each 15 minutes, or hour, or any shorter interval.
Email controller class
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
#Component
public class WeeklyReportScheduler {
#Autowired
private WeeklyReportService weeklyReportService;
#Scheduled(cron = "${cron.expression}")
public void sendWeeklyReport(){
weeklyReportService.sendWeeklyReport();
}
}
Email service class:
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.MailException;
import org.springframework.stereotype.Service;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
#Service
public class WeeklyReportService {
#Value("${weekly.report.mail.subject}")
private String subject;
#Value("${weekly.report.mail.body}")
private String mailBody;
#Value("${mail.body.empty.report}")
private String emptyReportMailBody;
#Value("${receiver}")
private String receiver;
#Autowired
private MailService mailService;
#Autowired
private WeeklyReportLogDao weeklyReportLogDao;
#Autowired
private ProjectService projectService;
#Value("${export.path}")
private String exportDir;
protected final Log logger = LogFactory.getLog(getClass());
public void sendWeeklyReport(){
boolean emptyReport = true;
//retrieving attachment data 'projects'
if(projects.size() != 0){
emptyReport = false;
}
String body = "";
if(emptyReport){
body = emptyReportMailBody;
} else {
body = mailBody;
}
SimpleDateFormat format = new SimpleDateFormat("MM/dd/YYYY");
String dateString = format.format(new Date());
String mailSubject = subject + " " + dateString;
List recipients = new ArrayList<String>();
recipients.add(receiver);
String fileName = mailSubject.replace(" ", "_").replace("/", "_");
WeeklyReportExcelExport excelExport = new WeeklyReportExcelExport(exportDir, fileName);
excelExport.createReport(projects);
File excelFile = excelExport.saveToFile();
File[] attachments = new File[1];
attachments[0] = excelFile;
boolean sent = false;
String exceptionMessage = "";
for(int i=0; i<3; i++){
try {
logger.info("Sending Attempt: " + i+1);
Thread.sleep(10000);
mailService.mail(recipients, mailSubject, body, attachments);
sent = true;
break;
} catch (Exception ex) {
logger.info("sending failed because: " + ex.getMessage() + " \nRe-attempting in 10 seconds");
exceptionMessage = ex.getMessage();
sent = false;
}
}
if(!sent){
weeklyReportLogDao.logFailedReporting(dateString, exceptionMessage);
}
//re-try 3 times in case of mail sending failure
}
MailService class:
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.List;
import java.util.Map;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.mail.MailException;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
public class MailServiceImpl implements MailService {
/** The From address for the e-mail. read from ant build properties file */
private String fromAddress;
/** The mail sender. */
private JavaMailSender mailSender;
/** Logger for this class and subclasses */
protected final Log logger = LogFactory.getLog(getClass());
public void mail(List<String> emailAddresses, String subject, String text, File[] attachments) throws MailException {
//System.out.println("mail: "+subject);
MimeMessage message = null;
// Fill in the From, To, and Subject fields.
try {
message = mailSender.createMimeMessage();
MimeMessageHelper messageHelper = new MimeMessageHelper(message, true);
messageHelper.setFrom(fromAddress);
for (String emailAddress : emailAddresses) {
messageHelper.addTo(emailAddress);
}
messageHelper.setSubject(subject);
// Fill in the body with the message text, sending it in HTML format.
messageHelper.setText(text, true);
// Add any attachments to the message.
if ((attachments != null) && (attachments.length != 0)) {
for (File attachment : attachments) {
messageHelper.addAttachment(attachment.getName(), attachment);
}
}
}
catch(MessagingException mse) {
String warnMessage = "Error creating message.";
logger.warn(warnMessage);
throw (new RuntimeException(warnMessage, mse));
}
try {
mailSender.send(message);
} catch (Exception ex){
logger.info("Exception sending message: " + ex.getMessage());
}
}
}
you might have duplicate entries on your argument emailAddresses, try moving it to treeset if you cant ensure duplicate entries from the repository layer

Junit Dynamic Test Cases data reading from file?

I have a scenario where to test the api using the payload coming from text file.Each line in file represents one payload.How can I dynamically generate test cases based on the above scenario.
I tried as below calling one test from other ,but i can only see paraent test passed.
import com.jayway.restassured.http.ContentType;
import com.jayway.restassured.response.Response;
import org.junit.Before;
import org.junit.Test;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import static com.jayway.restassured.RestAssured.given;
public class ExampleTest
{
private TestUtil testUtil;
String payload;
#Before
public void init()
{
testUtil = new TestUtil();
}
#Test
public void runAllTests() throws IOException
{
List<String> request = getFileDataLineByLine();
for(String fileRequest:request)
{
payload=fileRequest;
if(null!=payload) {
testExampleTest();
}
}
}
#Test
public void testExampleTest()
{
String uri = "http://localhost:8080/url";
Response response = given()
.contentType(ContentType.JSON)
.body(payload)
.post(uri)
.then()
.statusCode(200)
.extract()
.response();
}
private List<String> getFileDataLineByLine() throws IOException {
File file = testUtil.getFileFromResources();
if (file == null)
return null;
String line;
List<String> stringList = new ArrayList<>();
try (FileReader reader = new FileReader(file);
BufferedReader br = new BufferedReader(reader))
{
while ((line = br.readLine()) != null)
{
stringList.add(line);
System.out.println(line);
}
}
return stringList;
}
File Reading Class:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
public class TestUtil
{
public File getFileFromResources()throws IOException
{
TestUtil testUtil = new TestUtil();
File file = testUtil.getFileFromResources("testdata.txt");
return file;
}
// get file from classpath, resources folder
private File getFileFromResources(String fileName) {
ClassLoader classLoader = getClass().getClassLoader();
URL resource = classLoader.getResource(fileName);
if (resource == null) {
throw new IllegalArgumentException("file is not found!");
} else {
return new File(resource.getFile());
}
}
}
How can i generate test cases dynamically by taking input from file?
If you can convert your file JUnitParams supports loading data from a CSV.
Using an example from the above link's repository:
public class PersonTest {
#Test
#FileParameters("src/test/resources/test.csv")
public void loadParamsFromCsv(int age, String name) {
assertFalse(age > 120);
}
}

PlayFramework how to access list from super controller

I am completing my university project, but I encountered weird problem. Since I am a student, apologize in the adavance if it is prosaic.
I have my BasicCommonController which has List backendErrors = new ArrayList<>()
, and I have another Controller which extends BasicCommonController, and I'm able to access backendErrors list from BasicCommonController, but I am not able
to put new Element to the list, wchich is always empty. I have tried to access via super.backendErrors, but it also does not work.
How to add some error to the super.backendErrors and access it in another Controllers
this is abstract controller:
package controllers;
import org.apache.commons.lang3.StringUtils;
import play.Logger;
import play.Play;
import play.mvc.Controller;
import java.util.ArrayList;
import java.util.List;
/**
* Created by vv on 22.04.2017.
*/
public class BasicAbstractController extends Controller {
public static final String GO_HOME = "/";
public List<String> backendErrors = new ArrayList<>();
public static String getPlaceToObserve(){
String place = Play.application().configuration().getString("storage.place");
if(StringUtils.isNotBlank(place)){
return place;
}
return StringUtils.EMPTY;
}
public static String getServerInstance(){
String instance = Play.application().configuration().getString("storage.place");
if(StringUtils.isNotBlank(instance)){
return instance;
}
return StringUtils.EMPTY;
}
}
this is example controller
package controllers;
import com.google.common.io.Files;
import com.sun.org.apache.regexp.internal.RE;
import constans.AppCommunicates;
import play.Logger;
import play.mvc.Http;
import play.mvc.Result;
import util.FileUtil;
import java.io.File;
import java.io.IOException;
import java.util.List;
/**
* Created by vv on 22.04.2017.
*/
public class FileUploadController extends BasicAbstractController {
public Result upload() {
Http.MultipartFormData<File> body = request().body().asMultipartFormData();
Http.MultipartFormData.FilePart<File> picture = body.getFile("picture");
if (picture != null) {
String fileName = picture.getFilename();
String contentType = picture.getContentType();
File file = picture.getFile();
File fileToSave = new File(getPlaceToObserve() + "/" + picture.getFilename());
try{
Files.copy(file,fileToSave);
}
catch (IOException ioe){
Logger.error("Unable to write file");
}
Logger.error("File Handled Cuccessfully");
return redirect(GO_HOME);
} else {
flash("error", "Missing file");
return badRequest();
}
}
public Result delete(String fileName){
List<File> files = FileUtil.getCurrentFileNames();
File fileToDelete = null;
for (File file : files) {
if(file.getName().equals(fileName)){
fileToDelete = file;
break;
}
}
boolean deletionResult = FileUtil.deleteGivenFile(fileToDelete);
if(!deletionResult){
// i am not able to add smthg here
backendErrors.add(AppCommunicates.UNABLE_TO_DELETE_FILE);
}
return redirect(GO_HOME);
}
}
I am not able to add nor access list from other controllers

Categories

Resources