confirmation email - create templae and combine it with an object - java

I need to implement email confirmation in my java web application. I am stuck with the email I have to send to the user.
I need to combine a template (of an confirmation email) with the User object and this will be the html content of the confirmation email.
I thought about using xslt as the template engine but I don't have xml form of the User object and don't really know how to create a xml from User instance.
I thought about jsp, but how do I render jsp page with an object and get the html as a result?
Any idea what packages I can use in order to create templae and combine it with an object?

I have used the following before. I seem to recall it wasn't complicated
http://velocity.apache.org/

How complex is the user object? If it's just five string-valued fields (say) you could simply supply these as string parameters to the transformation, avoiding the need to build XML from your Java data.
Alternatively, Java XSLT processors typically provide some way to invoke methods on Java objects from within the XSLT code. So you could supply the Java object as a parameter to the stylesheet and invoke its methods using extension functions. The details are processor-specific.

Instead of learning a new code, debug other's complicate code I decided to write my own small and suitable util:
public class StringTemplate {
private String filePath;
private String charsetName;
private Collection<AbstractMap.SimpleEntry<String, String>> args;
public StringTemplate(String filePath, String charsetName,
Collection<AbstractMap.SimpleEntry<String, String>> args) {
this.filePath = filePath;
this.charsetName=charsetName;
this.args = args;
}
public String generate() throws FileNotFoundException, IOException {
StringBuilder builder = new StringBuilder();
BufferedReader reader = new BufferedReader(new InputStreamReader(
getClass().getResourceAsStream(filePath),charsetName));
try {
String line = null;
while ((line = reader.readLine()) != null) {
builder.append(line);
builder.append(System.getProperty("line.separator"));
}
} finally {
reader.close();
}
for (AbstractMap.SimpleEntry<String, String> arg : this.args) {
int index = builder.indexOf(arg.getKey());
while (index != -1) {
builder.replace(index, index + arg.getKey().length(), arg.getValue());
index += arg.getValue().length();
index = builder.indexOf(arg.getKey(), index);
}
}
return builder.toString();
}
}

Related

How to loop this test with different csv row?

I am beginner with selenium tests. I wrote this code and it works, but I need to loop this test with another csv line.
I spent almost 10 hours trying to do this.
Scenario of what I am trying to do:
The web browser is opening go to url
login with data from CSV file from first line
Driver is restarting and do the same but with data from second line from csv file.
I also tried to restart test with aftermethod/afterclass but it's not working.
public class CSVdataread {
private WebDriver driver;
String baseUrl = "URL";
String CSV_file = "C:\\Users\\xxxxxxxxxxx\\Desktop\\TestData.csv";
#BeforeClass
public void openBrowser() {
System.setProperty("webdriver.chrome.driver", "C:\\Users\\xxxxxxxxxxxx\\Desktop\\webdriver\\chromedriver.exe");
driver = new ChromeDriver();
driver.navigate().to("URL");
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
}
#Test
public void verify_Search() throws InterruptedException, IOException {
CSVReader reader = new CSVReader(new FileReader(CSV_file));
String[] cell;
while((cell = reader.readNext()) != null)
for (int i = 0; i < 1; i++) {
String name = cell[i];
String email = cell[i + 1];
String baseUrl = "http://xxxxx.xxx/xxxx/";
driver.findElement(By.xpath("//input[#id='useridFormField-inputEl']")).sendKeys(name);
driver.findElement(By.xpath("//input[#id='userpasswordFormField-inputEl']")).sendKeys(email);
{
driver.quit();
}
}
}
}
JUnit 4 solution. This one is going to be huge...
First, let's start off with CSVReader and some good practices plus code readability. In your test, you read CSV data and use them in your tests. It's not the test's responsibility to read data. The test should already have all the data provided to it. It's called DataProvider. This term is actually used in TestNG testing framework, just like #user861594 suggested.
So, you should have something to provide data to your tests. But this already Step #2. Since you know you will read data row-by-row from CSV file, you should create a proper class to read the data from CSV.
Here's an example:
public class CSVReader {
private static final String DEFAULT_SEPARATOR = ",";
private BufferedReader reader;
private List<String> lines;
public CSVReader(File file) throws FileNotFoundException {
this.reader = new BufferedReader(new FileReader(file));
lines = this.reader.lines().collect(Collectors.toList());
}
public String[] getRow(int rowNumber) {
return lines.get(rowNumber).split(DEFAULT_SEPARATOR);
}
public int getRowCount() {
return lines.size();
}
}
The CSVReader constructor accepts a File as an argument and creates proper objects to read data in a specific manner (for example: read as String). Then, the data in the CSV file is read, just like in normal TXT file by saving the lines in the memory for later use.
Then we create 2 methods. First is getRowCount which gives us the total number of row/set of data.
Second is getRow which collect the specific row from the list and saves it to String[] array for later use.
String[] array has a presentation like 1 Excel row:
data index 0 | data index 1 | data index 2 | data index 3
We have a class which allows us to read the file in an easy matter. Let's create the DataProvider
To provide data to tests, we need to use #Parameters annotation and return Collection<Object[]> to our test. I will talk later about that.
So, let's implement it in our DataProvider
public class CSVDataProvider {
public Collection<Object[]> getData() throws FileNotFoundException {
CSVReader reader = new CSVReader(new File("C:\\Users\\xxxxxxxxxxx\\Desktop\\TestData.csv"));
int rowCount = reader.getRowCount();
Object[][] data = new Object[rowCount][2];
for (int i = 0; i < rowCount; i++) {
Object[] singleRow = reader.getRow(i);
data[i][0] = singleRow[0];
data[i][1] = singleRow[1];
}
return Arrays.asList(data);
}
}
I assume that you have only logins and passwords in the CSV file. That's why I created a 2-dimensional array new Object[rowCount][2]. We create the array by providing how many elements it has to store and we know how many rows we have from rowCount variable.
2 means we have only 2 data per row. Login and password. If you want to use additional element, for example - the role of the user, you can modify to [3]
In the for loop we are transforming the data from the CSV file to array and return it for later use.
Now, let's talk about our test class.
#RunWith(Parameterized.class)
public class OurTest {
private String login, password;
public OurTest(String login, String password) {
this.login = login;
this.password = password;
}
#Parameterized.Parameters(name = "{index}: Login: ({0}) Password: ({1})")
public static Collection<Object[]> data() throws FileNotFoundException {
return new CSVDataProvider().getData();
}
#Test
public void test() {
System.out.println(String.format("login : %s | Password: %s", login, password));
}
}
In order to pass the parameters from DataProvider to our test, we need to
1. Annotate the class with #RunWith(Parameterized.class)
2. Create a method returning Collection<Object[]> with annotation#Parameters`
3. Create a constructor reflecting what kind of data do we accept.
Regarding point 3, that's why I created a 2 argument constructor with String login and String password. We are passing those 2 parameters. JUnit will create a new instance of OurTest and pass different row for each test.
In the test method I just printed the data we've got from the DataProvider
I do not present a fully working solution because I want you to try to adjust your test to learn this specific approach. It's also called Data-driven Testing.
We have only 1 test method but each line in the CSV file will run as a separate test.
Hope it helps!
Your while loop looks broken. The for loop inside the while loop seems to mess up your login procedure.
while((cell = reader.readNext())!=null) { // iterate through csv file
String name = cell[0]; // cell is current row, you need first column for name
String email = cell[1]; // second column for email (as password?)
// what do you want to do with baseUrl here?
driver.findElement(By.xpath("//input[#id='useridFormField-inputEl']")).sendKeys(name);
driver.findElement(By.xpath("//input[#id='userpasswordFormField-inputEl']")).sendKeys(email);
// you need to check the successful login here
// then logout and open main page
// do not quit before you are finished
}
// quit after the loop is finished
driver.quit();
Without any knowledge of the website it is impossible to tell you how to check successful login and perform logout.
May I suggest you put some effort in learning the ropes with a less complex task? You seem to have a lot of trouble with basic Java elements. Never stop learning.
It looks you want to iterate your test with set of test data. In that case you should use TestNG data provider feature.
public class CSVdataread {
private WebDriver driver;
String baseUrl = "URL";
String CSV_file = "C:\\Users\\xxxxxxxxxxx\\Desktop\\TestData.csv";
#BeforeMethod
public void openBrowser() {
System.setProperty("webdriver.chrome.driver", "C:\\Users\\xxxxxxxxxxxx\\Desktop\\webdriver\\chromedriver.exe");
driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
}
#Test(dataProvider="users-data")
public void verify_Search(String name, String email) throws InterruptedException, IOException {
String baseUrl = "http://xxxxx.xxx/xxxx/";
driver.navigate().to(baseUrl);
driver.findElement(By.xpath("//input[#id='useridFormField-inputEl']")).sendKeys(name);
driver.findElement(By.xpath("//input[#id='userpasswordFormField-inputEl']")).sendKeys(email);
}
//This method will provide data to any test method that declares that its Data Provider
#DataProvider(name = "users-data")
public Iterator<Object[]> createDataFromCSV() {
CSVReader reader = new CSVReader(new FileReader(CSV_file));
List<Object[]> data = new ArrayList<Object[]>();
//read csv data to list
return data.iterator();
}
#AfterMethod
public void closeBrowser() {
driver.quit();
}
}
You can also utilize available data-provider-extension. For example, with qaf You don't need to write code for driver management or for data provider. Your test class will look like below:
public class CSVdataread extends WebDriverTestCase{
#QAFDataProvider(dataFile="resources/user-data.csv")
#Test()
public void verify_Search(String name, String email) throws InterruptedException, IOException {
String baseUrl = "http://xxxxx.xxx/xxxx/";
getDriver().navigate().to(baseUrl);
getDriver().findElement(By.xpath("//input[#id='useridFormField-inputEl']")).sendKeys(name);
//another way of finding element...
getDriver().findElement("xpath=//input[#id='userpasswordFormField-inputEl']").sendKeys(email);
}
}

Modifying JSON output for for two different functions

I have two functions that each take in an array list descriptors. I am trying to print different JSON outputs for each respective function. I am using the Gson library to help me accomplish this task. I use a Client Data model object to help format the JSON correctly. Attached below are the getters and setters for this.
import java.util.ArrayList;
import java.util.List;
import com.google.gson.annotations.SerializedName;
public class ClientData {
#SerializedName("TrialCountryCodes")
private List<String> trialCountryCodes;
#SerializedName("CancerGenePanel")
private String cancerGenePanel;
public ClientData() {
this.trialCountryCodes = new ArrayList<String>();
}
public List<String> getTrialCountryCodes() {
return trialCountryCodes;
}
public void setTrialCountryCodes(List<String> trialCountryCodes) {
this.trialCountryCodes = trialCountryCodes;
}
public String getCancerGenePanel() {
return cancerGenePanel;
}
public void setCancerGenePanel(String cancerGenePanel) {
this.cancerGenePanel = cancerGenePanel;
}
}
The problem comes in with the Trial Country Codes. When I call one function I want Trial Country Codes to be visible in the JSON output. When I call the other one I don't want Country Codes to be visible. Attached below are the two functions one takes in one file and the other takes in two files. When the function has one file I don't want Trial Country Codes to be visible. When the function has two files I do want Trial Country Codes to be visible
descriptors = HelperMethods.getBreastCarcinomaDescriptorsFromCsvFile("/Users/edgarjohnson/eclipse-workspace/CsvToJson/src/in.csv");
descriptors = HelperMethods.getBreastCarcinomaDescriptorsFromCsvFile("/Users/edgarjohnson/eclipse-workspace/CsvToJson/src/in.csv", "/Users/edgarjohnson/eclipse-workspace/CsvToJson/src/EU.csv");
HelperMethods.writeJsonFile(descriptors, "JsonOutput.json");
More BackGround info: I am getting these values from a CSV file in which I read the CSV file and write the JSON output to multiple files. This is the code that I use to format my JSON file:
public static List<BreastCarcinomaDescriptor> getBreastCarcinomaDescriptorsFromCsvFile(String fileName, String fileName2) {
List<BreastCarcinomaDescriptor> descriptorsAndCountrycodes = new ArrayList<BreastCarcinomaDescriptor>();
BufferedReader bufferedCsvFile = HelperMethods
.getCsvFileBuffer(fileName);
BufferedReader bufferedCsvFile2 = HelperMethods
.getCsvFileBuffer(fileName2);
List<String> lines = new ArrayList<String>();
List<String> line2 = new ArrayList<String>();
HelperMethods.readCsvToStrings(lines, bufferedCsvFile);
HelperMethods.readCsvToStrings(line2, bufferedCsvFile2);
List<String> countryList = new ArrayList<String>();
System.out.println(line2);
//populate the country list using file2
countryList = Arrays.asList(line2.get(0).split(","));
System.out.println(countryList);
for (String line : lines) {
BreastCarcinomaDescriptor descriptor= getBreastCarcinomaDescriptorFromCsvLine(line);
//enrich this object with country code property
descriptor.getClientData().setTrialCountryCodes(countryList);
descriptorsAndCountrycodes.add(descriptor);
}
return descriptorsAndCountrycodes;
}
private static BreastCarcinomaDescriptor getBreastCarcinomaDescriptorFromCsvLine(String line) {
BreastCarcinomaDescriptor breastCarcinomaDescriptor = new BreastCarcinomaDescriptor();
String[] data = line.split(",");
breastCarcinomaDescriptor.setBatchName(data[0]);
breastCarcinomaDescriptor.getMetadata().setCharset("utf-8");
breastCarcinomaDescriptor.getMetadata().setSchemaVersion("1.5");
if(data.length > 5) {
breastCarcinomaDescriptor.getSampleInfo().setAge(new Integer(data[5].trim()));
}
breastCarcinomaDescriptor.getSampleInfo().setCancerType(data[3].trim());
if(data.length>4) {
breastCarcinomaDescriptor.getSampleInfo().setGender(data[4].trim());
}
breastCarcinomaDescriptor.getFiles().add(data[1].concat(".*"));
// breastCarcinomaDescriptor.getClientData().getTrialCountryCodes().add(descriptorsAndCountrycodes[]);
//breastCarcinomaDescriptor.getClientData().getTrialCountryCodes().add("20");
breastCarcinomaDescriptor.getClientData().setCancerGenePanel("");
breastCarcinomaDescriptor.setCaseName(data[1]);
return breastCarcinomaDescriptor;
}
What I've Tried: I tried using custom serialization to only display Trial Country Codes when we take in one file but I am having trouble with this.
Does anyone have any ideas how I can accomplish this task. I feel like the solution is trivial. However, I don't know the Gson Library too well and I am new to java.
How formatted output should look for function that takes in 1 file:
How formatted output should look for function that takes in 2 files:
You can register two different TypeAdapters which serialize into the format you want depending on which function gets called. Then each of your functions uses it's own type adapter and can control the details of the transformation.
First function
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(ClientData.class, new ClientDataWithCancerGenePanelAdapter());
Gson gson = builder.create();
Second function:
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(ClientData.class, new ClientDataWithTrialCountryCodesAdapter());
Gson gson = builder.create();

converting xml to java objects with xstream in java

I have an xml ans i want to make it objects , i am using xsteam for this and I have added xstream jars in my classpath..
below is my xml...
<Eurexflows xmlns:eur="http://www.eurexchange.com/EurexIRSFullInventoryReport" xmlns:fpml="http://www.fpml.org/FpML-5/confirmation">
<EurexMessageObject>
<CCPTradeId>109599</CCPTradeId>
<novDateTime>2012-02-15 10:59:00.0</novDateTime>
</EurexMessageObject>
<EurexMessageObject>
<CCPTradeId>122270</CCPTradeId>
<novDateTime>2012-06-29 18:59:00.0</novDateTime>
</EurexMessageObject>
</Eurexflows>
below is my pojo...
public class EurexMessageObject {
private Long CCPTradeId;
private String migratedDate;
public Long getCCPTradeId() {
return CCPTradeId;
}
public void setCCPTradeId(Long cCPTradeId) {
CCPTradeId = cCPTradeId;
}
public String getMigratedDate() {
return migratedDate;
}
public void setMigratedDate(String migratedDate) {
this.migratedDate = migratedDate;
}
}
and in my main class I have coded this way..
String xmlInputtra="C:\\Rahul\\InputXml\\Xmloutput.xml";
try
{
// get XStream instance and set required aliases
XStream xstream = new XStream();
xstream.alias("EurexMessageObject", com.rbos.gdspc.eurex.EurexMessageObject.class);
// prepare cash flow message from xslt output
EurexMessageObject eurexflowMsg = (EurexMessageObject) xstream.fromXML(xmlInputtra);
System.out.println(eurexflowMsg.toString());
}catch(Exception e)
{
e.printStackTrace();
}
now upon debuging I am getting the following exception..please advise how can I overcome from this
com.thoughtworks.xstream.io.StreamException: : only whitespace content allowed before start tag and not C (position: START_DOCUMENT seen C... #1:1)
Well,the thing that is overlooked here is how you are reading in the XML file.you are using the method fromXML which is expecting the actual XML input and not the file name. So when it parses your xml (which is "Xmloutput.xml" not the actual xml)
I suggest you to use a FileReader/BufferedReader in order to get the contents of the XML back. Something like this should work:
XStream instream = new XStream();
BufferedReader br = new BufferedReader(new FileReader("Xmloutput.xml"));
StringBuffer buff = new StringBuffer();
String line;
while((line = br.readLine()) != null){
buff.append(line);
}
EurexMessageObject eurexflowMsg = (EurexMessageObject)instream.fromXML(buff.toString());
I hope it will help you, best regards.
Here path for XML file:
String xmlInputtra="C:\\Rahul\\InputXml\\Xmloutput.xml";
is treated as XML contents,
so you need to pass as String for that you can read file and pass to constructor.

Ignore whitespace while converting XML to JSON using XStream

I'm attempting to establish a reliable and fast way to transform XML to JSON using Java and I've started to use XStream to perform this task. However, when I run the code below the test fails due to whitespace (including newline), if I remove these characters then the test will pass.
#Test
public void testXmlWithWhitespaceBeforeStartElementCanBeConverted() throws Exception {
String xml =
"<root>\n" +
" <foo>bar</foo>\n" + // remove the newlines and white space to make the test pass
"</root>";
String expectedJson = "{\"root\": {\n" +
" \"foo\": bar\n" +
"}}";
String actualJSON = transformXmlToJson(xml);
Assert.assertEquals(expectedJson, actualJSON);
}
private String transformXmlToJson(String xml) throws XmlPullParserException {
XmlPullParser parser = XppFactory.createDefaultParser();
HierarchicalStreamReader reader = new XppReader(new StringReader(xml), parser, new NoNameCoder());
StringWriter write = new StringWriter();
JsonWriter jsonWriter = new JsonWriter(write);
HierarchicalStreamCopier copier = new HierarchicalStreamCopier();
copier.copy(reader, jsonWriter);
jsonWriter.close();
return write.toString();
}
The test fails the exception:
com.thoughtworks.xstream.io.json.AbstractJsonWriter$IllegalWriterStateException: Cannot turn from state SET_VALUE into state START_OBJECT for property foo
at com.thoughtworks.xstream.io.json.AbstractJsonWriter.handleCheckedStateTransition(AbstractJsonWriter.java:265)
at com.thoughtworks.xstream.io.json.AbstractJsonWriter.startNode(AbstractJsonWriter.java:227)
at com.thoughtworks.xstream.io.json.AbstractJsonWriter.startNode(AbstractJsonWriter.java:232)
at com.thoughtworks.xstream.io.copy.HierarchicalStreamCopier.copy(HierarchicalStreamCopier.java:36)
at com.thoughtworks.xstream.io.copy.HierarchicalStreamCopier.copy(HierarchicalStreamCopier.java:47)
at testConvertXmlToJSON.transformXmlToJson(testConvertXmlToJSON.java:30)
Is there a way to to tell the copy process to ignore the ignorable white space. I cannot find any obvious way to enable this behaviour, but I think it should be there. I know I can pre-process the XML to remove the white space, or maybe just use another library.
update
I can work around the issue using a decorator of the HierarchicalStreamReader interface and suppressing the white space node manually, this still does not feel ideal though. This would look something like the code below, which will make the test pass.
public class IgnoreWhitespaceHierarchicalStreamReader implements HierarchicalStreamReader {
private HierarchicalStreamReader innerHierarchicalStreamReader;
public IgnoreWhitespaceHierarchicalStreamReader(HierarchicalStreamReader hierarchicalStreamReader) {
this.innerHierarchicalStreamReader = hierarchicalStreamReader;
}
public String getValue() {
String getValue = innerHierarchicalStreamReader.getValue();
System.out.printf("getValue = '%s'\n", getValue);
if(innerHierarchicalStreamReader.hasMoreChildren() && getValue.length() >0) {
if(getValue.matches("^\\s+$")) {
System.out.printf("*** White space value suppressed\n");
getValue = "";
}
}
return getValue;
}
// rest of interface ...
Any help is appreciated.
Comparing two XML's as String objects is not a good idea. How are you going to handle case when xml is same but nodes are not in the same order.
e.g.
<xml><node1>1</node1><node2>2</node2></xml>
is similar to
<xml><node2>2</node2><node1>1</node1></xml>
but when you do a String compare it will always return false.
Instead use tools like XMLUnit. Refer to following link for more details,
Best way to compare 2 XML documents in Java

running java application

I need to test the below mentioned method by calling it locally by a main method
public TokenFilter create(TokenStream input) {
if (protectedWords != null){
input = new KeywordMarkerFilter(input,protectedWords);
}
return new KStemFilter(input);
}
The problem I'm facing is I need to pass a string as input, but I'm not sure how to parse it as a token stream.
Please help.
To get TokenString from a search text, you have to use Analyzer for that:
Analyzer analyzer = ...; // your analyzer
TokenStream tokenStream = analyzer.tokenStream(null, new StringReader(searchText));
Note that it should be the same analyzer that is used to build the index.

Categories

Resources