I am deeply sorry for this messy title, but I am completly lost on why this can happen.
I am trying to parse a JSON String using Jackson. My code is simple:
import com.fasterxml.jackson.databind.ObjectMapper;
import formatter.Tweet;
import com.fasterxml.jackson.databind.DeserializationFeature;
public class FormatterTester {
static String tweet = "{\"created_at\":\"Fri May 03 11:43:17 +0000 2019\",\"id\":1124278249620566017,\"id_str\":\"1124278249620566017\",\"text\":\"RT #entkom: '\\u0e40\\u0e0b\\u0e49\\u0e19\\u0e15\\u0e4c-\\u0e28\\u0e38\\u0e20\\u0e1e\\u0e07\\u0e29\\u0e4c' \\u0e41\\u0e08\\u0e01\\u0e04\\u0e27\\u0e32\\u0e21\\u0e19\\u0e48\\u0e32\\u0e23\\u0e31\\u0e01 \\u0e21\\u0e2d\\u0e1a\\u0e04\\u0e27\\u0e32\\u0e21\\u0e2a\\u0e38\\u0e02\\u0e43\\u0e2b\\u0e49\\u0e41\\u0e1f\\u0e19\\u0e04\\u0e25\\u0e31\\u0e1a https:\\/\\/t.co\\/hBbi5hzEH8\",\"source\":\"\\u003ca href=\\\"http:\\/\\/twitter.com\\/download\\/android\\\" rel=\\\"nofollow\\\"\\u003eTwitter for Android\\u003c\\/a\\u003e\",\"truncated\":false,\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1062336001941504001,\"id_str\":\"1062336001941504001\",\"name\":\"\\ud83d\\udc0a\\u26bd\\ud83d\\udc2f\\ud83c\\udfb8\\ud83d\\udc99sugajin\\/\\/\\ud83d\\udc9a\\ud83d\\udc7b\\ud83d\\udc32\\ud83d\\udc0a\",\"screen_name\":\"sugajinBTS1\",\"location\":null,\"url\":null,\"description\":\"#BTS\\u597d\\u304d\\ud83d\\udc95\\u30b8\\u30f3\\u30cb\\u30e0\\u3088\\u308a\\u306e\\uff75\\uff99\\uff8d\\uff9f\\uff9d\\n#LGBTQ\\u304c\\u3082\\u3063\\u3068\\u7406\\u89e3\\u3055\\u308c\\u3066\\u6b32\\u3057\\u3044\\n#lovebychance\\u306e\\u6cbc\\u306b\\u30cf\\u30de\\u308a\\u4e2d\\n#season2\\u3068\\u3063\\u3066\\u3082\\u671f\\u5f85\\uff01\\uff01\\n#PinSon\\u2665SonPin\\n#2wish\\ud83d\\udc99\\ud83d\\udc9a\\n#Magus\\n#TeamReal\\n#LBCForever\\n\\u7121\\u8a00\\u30d5\\u30a9\\u30ed\\u30fc\\u5931\\u793c\\u3057\\u307e\\u3059\\ud83d\\ude47\",\"translator_type\":\"none\",\"protected\":false,\"verified\":false,\"followers_count\":61,\"friends_count\":224,\"listed_count\":0,\"favourites_count\":37785,\"statuses_count\":11611,\"created_at\":\"Tue Nov 13 13:26:54 +0000 2018\",\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"lang\":\"ja\",\"contributors_enabled\":false,\"is_translator\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":\"\",\"profile_background_image_url_https\":\"\",\"profile_background_tile\":false,\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"profile_image_url\":\"http:\\/\\/pbs.twimg.com\\/profile_images\\/1062337509701513216\\/5HFkKxoi_normal.jpg\",\"profile_image_url_https\":\"https:\\/\\/pbs.twimg.com\\/profile_images\\/1062337509701513216\\/5HFkKxoi_normal.jpg\",\"profile_banner_url\":\"https:\\/\\/pbs.twimg.com\\/profile_banners\\/1062336001941504001\\/1543643861\",\"default_profile\":true,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Fri May 03 01:29:52 +0000 2019\",\"id\":1124123879654301696,\"id_str\":\"1124123879654301696\",\"text\":\"'\\u0e40\\u0e0b\\u0e49\\u0e19\\u0e15\\u0e4c-\\u0e28\\u0e38\\u0e20\\u0e1e\\u0e07\\u0e29\\u0e4c' \\u0e41\\u0e08\\u0e01\\u0e04\\u0e27\\u0e32\\u0e21\\u0e19\\u0e48\\u0e32\\u0e23\\u0e31\\u0e01 \\u0e21\\u0e2d\\u0e1a\\u0e04\\u0e27\\u0e32\\u0e21\\u0e2a\\u0e38\\u0e02\\u0e43\\u0e2b\\u0e49\\u0e41\\u0e1f\\u0e19\\u0e04\\u0e25\\u0e31\\u0e1a https:\\/\\/t.co\\/hBbi5hzEH8\",\"source\":\"\\u003ca href=\\\"http:\\/\\/twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web Client\\u003c\\/a\\u003e\",\"truncated\":false,\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":69565234,\"id_str\":\"69565234\",\"name\":\"ent_komchadluek\",\"screen_name\":\"entkom\",\"location\":null,\"url\":null,\"description\":null,\"translator_type\":\"none\",\"protected\":false,\"verified\":false,\"followers_count\":6684,\"friends_count\":1115,\"listed_count\":86,\"favourites_count\":14,\"statuses_count\":31813,\"created_at\":\"Fri Aug 28 11:28:17 +0000 2009\",\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"lang\":\"en\",\"contributors_enabled\":false,\"is_translator\":false,\"profile_background_color\":\"FF6699\",\"profile_background_image_url\":\"http:\\/\\/abs.twimg.com\\/images\\/themes\\/theme11\\/bg.gif\",\"profile_background_image_url_https\":\"https:\\/\\/abs.twimg.com\\/images\\/themes\\/theme11\\/bg.gif\",\"profile_background_tile\":true,\"profile_link_color\":\"B40B43\",\"profile_sidebar_border_color\":\"CC3366\",\"profile_sidebar_fill_color\":\"E5507E\",\"profile_text_color\":\"362720\",\"profile_use_background_image\":true,\"profile_image_url\":\"http:\\/\\/pbs.twimg.com\\/profile_images\\/471687167\\/ent1_normal.jpg\",\"profile_image_url_https\":\"https:\\/\\/pbs.twimg.com\\/profile_images\\/471687167\\/ent1_normal.jpg\",\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"quote_count\":9,\"reply_count\":33,\"retweet_count\":584,\"favorite_count\":505,\"entities\":{\"hashtags\":[],\"urls\":[{\"url\":\"https:\\/\\/t.co\\/hBbi5hzEH8\",\"expanded_url\":\"http:\\/\\/www.komchadluek.net\\/news\\/ent\\/370511#.XMuZj_HCjrY.twitter\",\"display_url\":\"komchadluek.net\\/news\\/ent\\/37051\\u2026\",\"indices\":[52,75]}],\"user_mentions\":[],\"symbols\":[]},\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"filter_level\":\"low\",\"lang\":\"th\"},\"is_quote_status\":false,\"quote_count\":0,\"reply_count\":0,\"retweet_count\":0,\"favorite_count\":0,\"entities\":{\"hashtags\":[],\"urls\":[{\"url\":\"https:\\/\\/t.co\\/hBbi5hzEH8\",\"expanded_url\":\"http:\\/\\/www.komchadluek.net\\/news\\/ent\\/370511#.XMuZj_HCjrY.twitter\",\"display_url\":\"komchadluek.net\\/news\\/ent\\/37051\\u2026\",\"indices\":[64,87]}],\"user_mentions\":[{\"screen_name\":\"entkom\",\"name\":\"ent_komchadluek\",\"id\":69565234,\"id_str\":\"69565234\",\"indices\":[3,10]}],\"symbols\":[]},\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"filter_level\":\"low\",\"lang\":\"th\",\"timestamp_ms\":\"1556883797446\"}";
public static void main(String[]args) {
String valor_retorno= null;
Tweet tw;
try {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
tw = objectMapper.readValue(tweet, Tweet.class);
System.out.println("Check 3 - El formatter retorna:\n"+tw.toString());
valor_retorno = tw.toString();
} catch (Exception e) {
e.printStackTrace();
System.out.println("\nException " + e.getClass() + ": " + e.getMessage());
} finally {
System.out.println("\nReturn: Valor_retorno = "+valor_retorno);
}
}
}
If you run the code you'll see it works fine. Where is the problem then? I have to do this same operation on an Oracle NoSQL database. It's not important to know any of the parts related to the data retrieval since they work fine, I've tested them. The code is quite similar:
String data = new String(value.toByteArray(),StandardCharsets.UTF_8);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.configure(Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
tw = objectMapper.readValue(data, Tweet.class);
My objective is to obtain exactly the same result as in the first code. A String of values separated by '|' according of the attributes of my class Tweet.
However, this code is compressed in a Jar file, and run internally by the database over all the Tweets recorded. I can't see what happens nor debug it, but it produces the following exception:
com.fasterxml.jackson.core.JsonParseException: Illegal character ((CTRL-CHAR, code 0)): only regular white space (\r, \n, \t) is allowed between tokens
I've tried scaping the string "data" with StringEscapeUtils.escapeJava(data);
what then produces the following exception:
com.fasterxml.jackson.core.JsonParseException: Unexpected character ('\' (code 92)): expected a valid value (number, String, array, object, 'true', 'false' or 'null')
I've also tried scaping the string like this data.replace('\'', ' '); without success.
I can't understand after many tests, why it runs well on the demo I put here first and not on the actual project, having exactly the same dependencies.
For some reason, Jackson can't parse what I retrieve from the DataBase. This is most likely due to a problem of codification or decodification in the CentOS that my Docker container uses to hold the DB and where the script is invoqued and executed.
In the end, using Gson for the parsing was the best option, though it would still produce errors if you don't trim() the String. Apparently, for some reason the JSON came quoted twice. This is, ""JSON text"".
The code:
package formatter;
import java.io.*;
import java.lang.String;
import java.nio.charset.StandardCharsets;
import java.util.List;
import oracle.kv.*;
import com.google.gson.Gson;
import oracle.kv.KeyValueVersion;
import oracle.kv.exttab.Formatter;
public class TweetFormatter implements Formatter {
public TweetFormatter() {
super();
}
public String toOracleLoaderFormat(final KeyValueVersion kvv, final KVStore kvStore){
String valor_retorno= null;
Tweet tw; //antes sin null
BufferedWriter bf = FormatterUtils.getInstance().getWriter();
try {
final Key key = kvv.getKey();
final Value value = kvv.getValue();
Value.Format format = value.getFormat();
FormatterUtils.getInstance().writeLine(bf,"[Key: "+ key + ", Value:" +value.toByteArray()+ "]" + ". Format= "+ format.toString());
//Filtrar Clave
List<String> major = key.getMajorPath();
FormatterUtils.getInstance().writeLine(bf,"Check 1:\n Key is: "+key + "\n Key length is: "+major.size()
+ "\n Values are: "+major.toString() + "\n contains: "+major.contains("TweeterStream"));
Boolean contains = false;
for(String x : major) {
if(x.equals("TweeterStream")||x.equals("/TweeterStream")||x.equals("/TweeterStream/")) {
contains = true;
break;
}
}
//Parsear
if(contains){
String data = new String(value.toByteArray(),StandardCharsets.UTF_8);
data = data.trim();
tw = new Gson().fromJson(data,Tweet.class); //FUNCIONA
FormatterUtils.getInstance().writeLine(bf,"Check 3 - El formatter retorna:\n"+tw.toString());
valor_retorno = tw.toString();
}else{
FormatterUtils.getInstance().writeLine(bf,"\nEstoy en else");
}
FormatterUtils.getInstance().writeLine(bf,"\nestoy fuera del if-else");
} catch (Exception e) {
e.printStackTrace();
FormatterUtils.getInstance().writeLine(bf, "\nException " + e.getClass() + ": " + e.getMessage());
} finally {
FormatterUtils.getInstance().writeLine(bf,"\nReturn: Valor_retorno = "+valor_retorno);
FormatterUtils.getInstance().generateLog(bf);
}
return valor_retorno;
}
I would like to retrieve the list of Tags attached to a file in Windows 7 programatically. I am trying to create a mapping of file->tags that I can move across different platforms.
Is anyone aware of a library, or a way to get the 'Tags' values from command line? So far I have only been able to find ways to get basic file attributes such as Author, Date Created, etc.
I am unable to load PowerShell scripts on the computer unfortunately so am not able to make use of those features.
I tried using 'UserDefinedFileAttributeView' but that did not return any values, like so:
private LinkedList<String> windowsGetAllFileTags(File file) {
UserDefinedFileAttributeView fileAttributeView = Files.getFileAttributeView(file.toPath().toAbsolutePath(), UserDefinedFileAttributeView.class);
List<String> allAttributes = null;
try {
allAttributes = fileAttributeView.list();
} catch (IOException e) {
e.printStackTrace();
}
for(String attribute : allAttributes) {
System.out.println("Attribute = " + attribute);
}
return null;
}
An image of the Windows 7 Properties View
There is a Java library written and called as PE/COFF 4J on Github.
import java.io.IOException;
import org.boris.pecoff4j.PE;
import org.boris.pecoff4j.ResourceDirectory;
import org.boris.pecoff4j.ResourceEntry;
import org.boris.pecoff4j.constant.ResourceType;
import org.boris.pecoff4j.io.PEParser;
import org.boris.pecoff4j.io.ResourceParser;
import org.boris.pecoff4j.resources.StringFileInfo;
import org.boris.pecoff4j.resources.StringTable;
import org.boris.pecoff4j.resources.VersionInfo;
import org.boris.pecoff4j.util.ResourceHelper;
public class Main {
public static void main(String[] args) throws IOException {
PE pe = PEParser.parse("C:/windows/system32/notepad.exe");
ResourceDirectory rd = pe.getImageData().getResourceTable();
ResourceEntry[] entries = ResourceHelper.findResources(rd, ResourceType.VERSION_INFO);
for (int i = 0; i < entries.length; i++) {
byte[] data = entries[i].getData();
VersionInfo version = ResourceParser.readVersionInfo(data);
StringFileInfo strings = version.getStringFileInfo();
StringTable table = strings.getTable(0);
for (int j = 0; j < table.getCount(); j++) {
String key = table.getString(j).getKey();
String value = table.getString(j).getValue();
System.out.println(key + " = " + value);
}
}
}
}
Will print:
CompanyName = Microsoft Corporation
FileDescription = Notepad
FileVersion = 6.1.7600.16385 (win7_rtm.090713-1255)
InternalName = Notepad
LegalCopyright = © Microsoft Corporation. All rights reserved.
OriginalFilename = NOTEPAD.EXE
ProductName = Microsoft® Windows® Operating System
ProductVersion = 6.1.7600.16385
If you mention of obtaining tags of images or videos, #Drew Noakes has written Java library called as metadata-extractor for it.
Metadata metadata = ImageMetadataReader.readMetadata(imagePath);
To iterate all values in the file:
for (Directory directory : metadata.getDirectories()) {
for (Tag tag : directory.getTags()) {
System.out.println(tag);
}
}
You can also read specific values from specific directories:
// obtain the Exif SubIFD directory
ExifSubIFDDirectory directory
= metadata.getFirstDirectoryOfType(ExifSubIFDDirectory.class);
// query the datetime tag's value
Date date = directory.getDate(ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL);
The library is available for Maven users too.
In Windows PowerShell, you could grab it with a bit of help from PresentationCore.dll:
function Get-ImageTags {
param(
[string]$Path
)
Add-Type -AssemblyName PresentationCore
try {
$FileStream = (Get-Item $Path).Open('Open','Read')
$BitmapFrame = [System.Windows.Media.Imaging.BitmapFrame]::Create($FileStream)
$Tags = #($BitmapFrame.Metadata.Keywords |%{ $_ })
}
catch {
throw
return
}
finally {
if($FileStream){
$FileStream.Dispose()
}
}
return $Tags
}
Then use like:
$Tags = Get-ImageTags -Path path\to\file.jpeg
The $Tags variable will now contain an array of tags
what about Files.getAttribute
I didn't tried that but probably this could work:
Files.getAttribute(Paths.get("/some/dir","file.txt"), "description:tags")
Could any one help me in below issue
I want to pass test cases in QC through Java, I used con4j and reached till test sets but I am unable to fetch the test cases under respective test set.
could any one please help me in how to pass test cases in QC through com4j
import com.qc.ClassFactory;
import com.qc.ITDConnection;
import com.qc.ITestLabFolder;
import com.qc.ITestSetFactory;
import com.qc.ITestSetTreeManager;
import com.qc.ITestSetFolder;
import com.qc.IList;
import com.qc.ITSTest;
import com.qc.ITestSet;
import com.qc.ITestFactory;
import com4j.*;
import com4j.stdole.*;
import com4j.tlbimp.*;
import com4j.tlbimp.def.*;
import com4j.tlbimp.driver.*;
import com4j.util.*;
import com4j.COM4J;
import java.util.*;
import com.qc.IRun;
import com.qc.IRunFactory;
public class Qc_Connect {
public static void main(String[] args) {
// TODO Auto-generated method stub
String url="http://abc/qcbin/";
String domain="abc";
String project="xyz";
String username="132222";
String password="Xyz";
String strTestLabPath = "Root\\Test\\";
String strTestSetName = "TestQC";
try{
ITDConnection itd=ClassFactory.createTDConnection();
itd.initConnectionEx(url);
System.out.println("COnnected To QC:"+ itd.connected());
itd.connectProjectEx(domain,project,username,password);
System.out.println("Logged into QC");
//System.out.println("Project_Connected:"+ itd.connected());
ITestSetFactory objTestSetFactory = (itd.testSetFactory()).queryInterface(ITestSetFactory.class);
ITestSetTreeManager objTestSetTreeManager = (itd.testSetTreeManager()).queryInterface(ITestSetTreeManager.class);
ITestSetFolder objTestSetFolder =(objTestSetTreeManager.nodeByPath(strTestLabPath)).queryInterface(ITestSetFolder.class);
IList its1 = objTestSetFolder.findTestSets(strTestSetName, true, null);
//IList ls= objTestSetFolder.findTestSets(strTestSetName, true, null);
System.out.println("No. of Test Set:" + its1.count());
ITestSet tst= (ITestSet) objTestSetFolder.findTestSets(strTestSetName, true, null).queryInterface(ITSTest.class);
System.out.println(tst.name());
//System.out.println( its1.queryInterface(ITestSet.class).name());
/* foreach (ITestSet testSet : its1.queryInterface(ITestSet.class)){
ITestSetFolder tsFolder = (ITestSetFolder)testSet.TestSetFolder;
ITSTestFactory tsTestFactory = (ITSTestFactory)testSet.TSTestFactory;
List tsTestList = tsTestFactory.NewList("");
}*/
/* Com4jObject comObj = (Com4jObject) its1.item(0);
ITestSet tst = comObj.queryInterface(ITestSet.class);
System.out.println("Test Set Name : " + tst.name());
System.out.println("Test Set ID : " + tst.id());
System.out.println("Test Set ID : " + tst.status());
System.out.println("Test Set ID : " );*/
System.out.println(its1.count());
System.out.println("TestSet Present");
Iterator itr = its1.iterator();
System.out.println(itr.hasNext());
while (itr.hasNext())
{
Com4jObject comObj = (Com4jObject) itr.next();
ITestSet sTestSet = comObj.queryInterface(ITestSet.class);
System.out.println(sTestSet.name());
Com4jObject comObj2 = sTestSet.tsTestFactory();
ITestSetFactory test = comObj2.queryInterface(ITestSetFactory.class);
}
// ITSTest tsTest=null;
// tsTest.
//its1.
/* comObj = (Com4jObject) its1.item(1);
ITSTest tst2=comObj.queryInterface(ITSTest.class);*/
// System.out.println( tst2.name());
/* foreach (ITSTest tsTest : tst2)
{
IRun lastRun = (IRun)tsTest.lastRun();
if (lastRun == null)
{
IRunFactory runFactory = (IRunFactory)tsTest.runFactory;
String date = "20160203";
IRun run = (IRun)runFactory.addItem( date);
run.status("Pass");
run.autoPost();
}
}*/
}
catch(Exception e){
e.printStackTrace();
}
}
}
I know the post is quite old. I have to struggle alot in OTA with Java and couldn't get a complete post for solving the issue.
Now i have running code after too much research.
so thought of sharing my code in case someone is looking for help.
Here is complete Solution.
`
ITestFactory sTestFactory = (connection.testFactory())
.queryInterface(ITestFactory.class);
ITest iTest1 = (sTestFactory.item(12081)).queryInterface(ITest.class);
System.out.println(iTest1.execDate());
System.out.println(iTest1.name());
ITestSetFactory sTestSetFactory = (connection.testSetFactory())
.queryInterface(ITestSetFactory.class);
ITestSet sTestSet = (sTestSetFactory.item(1402))
.queryInterface(ITestSet.class);
System.out.println(sTestSet.name() + "\n Test Set ID" + sTestSet.id());
IBaseFactory testFactory1 = sTestSet.tsTestFactory().queryInterface(
IBaseFactory.class);
testFactory1.addItem(iTest1);
System.out.println("Test case has been Added");
System.out.println(testFactory1.newList("").count());
IList tsTestlist = testFactory1.newList("");
ITSTest tsTest;
for (int tsTestIndex = 1; tsTestIndex <= tsTestlist.count(); tsTestIndex++) {
Com4jObject comObj = (Com4jObject) tsTestlist.item(tsTestIndex);
tsTest = comObj.queryInterface(ITSTest.class);
if (tsTest.name().equalsIgnoreCase("[3]TC_OTA_API_Test")) {
System.out.println("Hostname" + tsTest.hostName() + "\n"
+ tsTest.name() + "\n" + tsTest.status());
IRun lastRun = (IRun) tsTest.lastRun();
// IRun lastRun = comObjRun.queryInterface(IRun.class);
// don't update test if it may have been modified by someone
// else
if (lastRun == null) {
System.out.println("I am here last Run = Null");
runFactory = tsTest.runFactory().queryInterface(
IRunFactory.class);
System.out.println(runFactory.newList("").count());
String runName = "TestRun_Automated";
Com4jObject comObjRunForThisTS = runFactory
.addItem(runName);
IRun runObjectForThisTS = comObjRunForThisTS
.queryInterface(IRun.class);
runObjectForThisTS.status("Passed");
runObjectForThisTS.post();
runObjectForThisTS.refresh();
}
}
}
`
Why not build a client to access the REST API instead of passing through the OTA interface?
Once you build a basic client, you can post runs and update their status quite easily.
If you use c#/vb.net this has been easily completed. But you are working on java, I would suggest to provide interface above dlls to deal with operation. This will be much more easier than using com4j.
Similar query, probably following may help you. I would suggest to drop idea of using com4j and use solution provided in thread below which is proven,fail safe and auto-recoverable.
QC API JAR to connect using java
it was always been difficult to use com4j specially for HPQC/ALM. As dlls for QC are faulty and there are memory leaking/allocation problems which crashes dll executions frequently on certain platforms.
I worked with a java-tutorial for mapReduce-Programming in MongoDB and ended up with the following Code:
package mapReduceExample;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.MapReduceCommand;
import com.mongodb.MapReduceOutput;
import com.mongodb.Mongo;
public class MapReduceExampleMain {
/**
* #param args
*/
public static void main(String[] args) {
Mongo mongo;
try {
mongo = new Mongo("localhost", 27017);
DB db = mongo.getDB("library");
DBCollection books = db.getCollection("books");
BasicDBObject book = new BasicDBObject();
book.put("name", "Understanding JAVA");
book.put("pages", 100);
books.insert(book);
book = new BasicDBObject();
book.put("name", "Understanding JSON");
book.put("pages", 200);
books.insert(book);
book = new BasicDBObject();
book.put("name", "Understanding XML");
book.put("pages", 300);
books.insert(book);
book = new BasicDBObject();
book.put("name", "Understanding Web Services");
book.put("pages", 400);
books.insert(book);
book = new BasicDBObject();
book.put("name", "Understanding Axis2");
book.put("pages", 150);
books.insert(book);
String map = "function()"
+ "{ "
+ "var category; "
+ "if ( this.pages > 100 ) category = 'Big Books'; "
+ "else category = 'Small Books'; "
+ "emit(category, {name: this.name});"
+ "}";
String reduce = "function(key, values)"
+ "{"
+ "return {books: values.length};"
+ "} ";
MapReduceCommand cmd = new MapReduceCommand(books, map, reduce,
null, MapReduceCommand.OutputType.INLINE, null);
MapReduceOutput out = books.mapReduce(cmd);
for (DBObject o : out.results()) {
System.out.println(o.toString());
}
//aufräumen
db.dropDatabase();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
This is a pretty simple reduce-Phase, but it does not what I want :(
The output is:
{ "_id" : "Big Books" , "value" : { "books" : 4.0}}
{ "_id" : "Small Books" , "value" : { "name" : "Understanding JAVA"}}
I would expect this:
{ "_id" : "Big Books" , "value" : { "books" : 4.0}}
{ "_id" : "Small Books" , "value" : { "books" : 1.0}}
Why does the reduce-Phase not give back the values.length in the case of a small book?
Greetings, Andre
Becuase if there is only one results the reduce is never run. Change it to be a finalise function or something.
A Basic Understanding of how mapReduce Works
Let us introduce the concepts of mapReduce
mapper - This is the stage that emit's the data to be fed into the reduce stage. It requires a key and a value be to sent. You can emit several times if you want in a mapper, but the requirements stay the same.
reducer - A reducer is called when there is more than one value of a given key to process the list of values that have been emitted for that key.
That said, since the mapper only emitted one key value your reducer was not called.
You can clean this up in finalise, but the behavior of the emit from the mapper going straight through is by standard design.
Open mongo shell and create a document with a undefined value:
> mongo
MongoDB shell version: 2.4.0
connecting to: test
> use mydb
switched to db mydb
> db.mycol.insert( {a_number:1, a_string:"hi world", a_null:null, an_undefined:undefined} );
> db.mycol.findOne();
{
"_id" : ObjectId("51c2f28a7aa5079cf24e3999"),
"a_number" : 1,
"a_string" : "hi world",
"a_null" : null,
"an_undefined" : null
}
As we can see, javascript translates the "undefined" value (stored in the db) to a "null" value, when showing it to the user. But, in the db, the value is still "undefined", as we are going to see with java.
Let's create a "bug_undefined_java_mongo.java" file, with the following content:
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.MongoClient;
public class bug_undefined_java_mongo
{
String serv_n = "myserver"; // server name
String db_n = "mydb"; // database name
String col_n = "mycol"; // collection name
public static void main(String[] args)
{
new bug_undefined_java_mongo().start();
}
public void start()
{
pr("Connecting to server ...");
MongoClient cli = null;
try
{
cli = new MongoClient( serv_n );
}
catch (Exception e)
{
pr("Can't connecto to server: " + e);
System.exit(1);
}
if (cli == null)
{
pr("Can't connect to server");
System.exit(1);
}
pr("Selecting db ...");
DB db_res = cli.getDB( db_n );
pr("Selecting collection ...");
DBCollection col = db_res.getCollection( col_n );
pr("Searching documents ...");
DBCursor cursor = null;
try
{
cursor = col.find( );
}
catch (Exception e)
{
pr("Can't search for documents: " + e);
System.exit(1);
}
pr("Printing documents ...");
try
{
while (cursor.hasNext())
{
Object doc_obj = cursor.next();
System.out.println("doc: " + doc_obj);
}
}
catch (Exception e)
{
pr("Can't browse documents: " + e);
return;
}
finally
{
pr("Closing cursor ...");
cursor.close();
}
}
public void pr(String cad)
{
System.out.println(cad);
}
}
After compiling and running it, we get this:
Connecting to server ...
Selecting db ...
Selecting collection ...
Searching documents ...
Printing documents ...
doc: { "_id" : { "$oid" : "51c2f0f85353d3425fcb5a14"} , "a_number" : 1.0 , "a_string" : "hi world" , "a_null" : null }
Closing cursor ...
We see that the "a_null:null" pair is shown, but... the "an_undefined:undefined" pair has disappeared! (both the key and the value).
Why? Is it a bug?
Thank you
Currently undefined is not supported by the java driver as there is no equivalent mapping in java.
Other drivers such as pymongo and the js shell handles this differently by casting undefined to None when representing the data, however it is a separate datatype and is deprecated in the bson spec.
If you need it in the java driver then you will have to code your own decoder factory and then set it like so:
collection.setDBDecoderFactory(MyDecoder.FACTORY);
A minimal example that has defined handling for undefined and factory is available on github in the horn of mongo repo.
I see, creating a factory could be a solution.
Anyway, probably many developers would find it useful the posibility of enabling a mapping in the driver to convert automatically "undefined" values to "null" value. For example, by calling a mapUndefToNull() method:
cli = new MongoClient( myserver );
cli.mapUndefToNull(true);
In my case, I'm running a MapReduce (it is Javascript code) on my collections, and I am having to explicitly convert the undefined values (generated when accessing to non existent keys) to null, in order to avoid Java driver to remove it:
try { value = this[ key ] } catch(e) {value = null}
if (typeof value == "undefined") value = null; // avoid Java driver to remove it
So, as a suggestion, I'd like the mapUndefToNull() method to be added to the Java driver. If possible.
Thank you