No exception for duplicates with gmongo - java

I have tried to insert duplicates into a mongodb database with both Groovy and Java. Java raises an exception while the groovy version just quietly ignores to insert the duplicate.
Here is some example code that illustrate this. I am running on OsX, Mongodb version 2.4.4. Can anyone enlighten me on this? Most grateful!
package chapter3
import com.gmongo.GMongo
import com.mongodb.BasicDBObject
import com.mongodb.DB
import com.mongodb.DBCollection
import com.mongodb.MongoClient
class TweetArchiveWithJava {
static void main(String[] args) {
new TweetArchiveWithJava()
}
private static final int ASCENDING = 1
TweetArchiveWithJava() {
duplicateInsertGroovy()
duplicateInsertJava()
}
def duplicateInsertJava() {
println "Inserting duplicates with Java"
MongoClient mongoClient = new MongoClient()
DB db = mongoClient.getDB("twitter-archive")
DBCollection tweets = db.getCollection("tweets")
tweets.remove(new BasicDBObject())
tweets.ensureIndex(new BasicDBObject("last_name", ASCENDING), "unique_index", true)
BasicDBObject insertedRecord = new BasicDBObject("last_name", "jones")
BasicDBObject duplicate = new BasicDBObject("last_name", "jones")
tweets.insert(insertedRecord)
System.out.println("Inserted first one")
printAllTweets(tweets)
tweets.insert(duplicate)
System.out.println("What?!! Should not be able to insert duplicates.")
printAllTweets(db)
}
private void duplicateInsertGroovy() {
println "Inserting duplicates with Groovy"
def mongo = new GMongo("127.0.0.1", 27017)
def db = mongo.getDB("twitter-archive")
DBCollection tweets = db.getCollection("tweets")
tweets.remove([:])
tweets.ensureIndex(new BasicDBObject("last_name", ASCENDING), "unique_index", true)
def jones = [last_name: "jones"]
tweets.insert(jones)
println "Inserted first Jones"
def duplicate = [last_name: "jones"]
tweets.insert(duplicate)
println "Succeeded inserting duplicate"
println "But only one record is found"
printAllTweets(tweets)
println "\n"
}
def printAllTweets(tweets) {
def cursor = tweets.find()
cursor.each { println it }
}
}

First, You you can use WriteResult for error indication:
def jones = [last_name: "jones"]
WriteResult rs = tweets.insert(jones)
println rs.error
//println "Inserted first Jones"
def duplicate = [last_name: "jones"]
rs = tweets.insert(duplicate)
//println "Succeeded inserting duplicate"
println rs.error
Prints:
null
E11000 duplicate key error index: twitter.tweets.$unique_index dup key: { : "jones" }
The reason for the difference is the WriteConcern:
The java method code uses {w=1} (acknowledged)
Whereas groovy method code uses {w=0} (normal)
Form DBTCPConnector
if ( concern.callGetLastError() ){
return _checkWriteError( db , port , concern );
}
else {
return new WriteResult( db , port , concern );
}
and in WriteConcern :
public boolean callGetLastError(){
if (_w instanceof Integer)
return (Integer) _w > 0;
return _w != null;
}
So the java method calls _checkWriteError behind the scenes - where an exception is thrown - and the groovy method just returns the write result.
The reason that you have different write concerns is initialization code:
You initialize MongoClient mongoClient = new MongoClient() in your java method, which internally uses WriteConcern.ACKNOWLEDGED.
In your groovy method, the GMongo constructor uses Mongo deprecated constructor which internally uses WriteConcern.NORMAL.
If you change tweets.insert(duplicate) to tweets.insert(duplicate, WriteConcern.ACKNOWLEDGED), you'll get an exception for the groovy method too

Not sure, but what happens if you change the groovy version to:
def jones = [last_name: "jones"] as BasicDBObject
tweets.insert(jones)
println "Inserted first Jones"
def duplicate = [last_name: "jones"] as BasicDBObject
tweets.insert(duplicate)

You can also use com.gmongo.GMongoClient. It has the same constructors as com.mongodb.MongoClient.

Related

Scala udf UnsupportedOperationException

I have a dataframe a2 written in scala :
val a3 = a2.select(printme.apply(col(“PlayerReference”)))
the column PlayerReference contains a string.
that calls an udf function :
val printme = udf({
st: String =>
val x = new JustPrint(st)
x.printMe();
})
this udf function calls a java class :
public class JustPrint {
private String ss = null;
public JustPrint(String ss) {
this.ss = ss;
}
public void printMe() {
System.out.println("Value : " + this.ss);
}
}
but i have this error for the udf :
java.lang.UnsupportedOperationException: Schema for type Unit is not supported
The goal of this exercise is to validate the chain of calls.
What should I do to solve this problem ?
The reason you're getting this error is that your UDF doesn't return anything, which, in terms of spark is called Unit.
What you should do depends on what you actually want, but, assuming you just want to track values coming through your UDF you should either change printMe so it returns String, or the UDF.
Like this:
public String printMe() {
System.out.println("Value : " + this.ss);
return this.ss;
}
or like this:
val printme = udf({
st: String =>
val x = new JustPrint(st)
x.printMe();
x
})

calling Stored Procedure String via Rest API returns empty instead of valid String

As a back-end developer, I would like to call stored procedure connecting Oracle 9i database to fetch the single output string.
In reality, the result of the output parameter as string, returns empty.
Would you please tell me what to modify the work?
Here is my rest controller:
#GetMapping(value = { "/third"})
public String getVariable (){
String result = "" ;
Connection conn;
conn = getConnection() ;
CallableStatement cstmt = null;
try {
String SQL = "{call pkg1234.get_pc_lookup_value_second(?,?)}";
cstmt = conn.prepareCall (SQL);
cstmt.setString(1, "TES");
cstmt.registerOutParameter(2, oracle.jdbc.OracleTypes.VARCHAR );
cstmt.execute();
String dddresult = cstmt.getString(2);
System.out.println(" Record :"+dddresult);
result = dddresult;
}
catch (SQLException e) {
System.out.println(" go this");
e.printStackTrace();
}
return result ;
}
Here is my stored procedure:
PROCEDURE get_pc_lookup_value_second (
i_lookup_code IN VARCHAR2,
o_lookup_value OUT VARCHAR2
)
o_lookup_value := '456';
END get_pc_lookup_value_second;
Try my own library for simplicity:
<dependency>
<groupId>com.github.buckelieg</groupId>
<artifactId>db-fn</artifactId>
<version>0.3.4</version>
</dependency>
And then in code:
try(DB db = new DB("your-connection-string")) {
String result = db.procedure("{call pkg1234.get_pc_lookup_value_second(?,?)}", P.in("TES"), P.out(JDBCType.VARCHAR)).call(cs -> cs.getString(2)).orElse("Unknown");
}
See more here
You have reported the following as your code:
try(DB db = new DB("jdbc:oracle:thin:username/password#10.8.12.6:1521:dev")) {
String thisString = db.procedure("{call b_pc_mob_portal_pkg.get_pc_lookup_value_second(?,?)}",
P.in("TES" , "i_lookup_code"),
P.out(JDBCType.LONGNVARCHAR , "o_lookup_value" )).call(cs -> cs.getString(2)).orElse("Unknown");
System.out.println( "thisString String :" + thisString );
}
You have reported that this gives:
[Ljava.lang.Object; cannot be cast to [Lbuckelieg.fn.db.P;
You have asked:
How can I check on whether this method need to be revised.
This is because you try to combine named parameters with anonymous ones. Either remove parameter names:
db.procedure("{call b_pc_mob_portal_pkg.get_pc_lookup_value_second(?,?)}", P.in("TES"), P.out(JDBCTtype.VARCHAR))...
or add names to procedure call statement:
db.procedure("{call b_pc_mob_portal_pkg.get_pc_lookup_value_second(:i_lookup_code,:o_lookup_value)}", P.in("i_lookup_code", "TES"), P.out(JDBCType.VARCHAR , "o_lookup_value" ))...
You have also reported that you have tried this code:
try(DB db = new DB("jdbc:oracle:thin:username/password#10.8.12.6:1521:dev")) {
String thisString = db.procedure("{call b_pc_mob_portal_pkg.get_pc_lookup_value_second(?,?)}",
P.in("TES" ),
P.out(JDBCType.VARCHAR )).call(cs -> cs.getString(2)).orElse("Unknown");
System.out.println( "thisString String :" + thisString );
}
And you have said:
when I do it in this way, it gives:
buckelieg.fn.db.SQLRuntimeException: [registerOutParameter not implemented]
I think the problem is in JDBC driver. Which version do you use? Can it be updated for newer one?
You have said that this is your database:
And also that you have downloaded:
OJDBC7.jar
https://www.oracle.com/database/technologies/jdbc-drivers-12c-downloads.html
Here is the Oracle IDE Version fetched by the Oracle SQL Developer
Very interesting. I will look into this issue.
As a temporal workaround I suggest to do the following:
Rewrite procedure as follows:
CREATE OR REPLACE FUNCTION b_pc_mob_portal_pkg.get_pc_lookup_value_second(IN param1 VARCHAR2 DEFAULT 'TES')
RETURN VARCHAR2 IS
BEGIN
RETURN '456';
END b_pc_mob_portal_pkg.get_pc_lookup_value_second;
And then in code:
String value = db.select("SELECT b_pc_mob_portal_pkg.get_pc_lookup_value_second(?) AS output FROM DUAL", "TES").single(rs -> rs.getString("output")).orElse("Unknown");
How about procedure?
Have you tried latest version (0.3.6) of library?
<dependency>
<groupId>com.github.buckelieg</groupId>
<artifactId>db-fn</artifactId>
<version>0.3.6</version>
</dependency>
#raju,
It may help you,Using Jpa Template with Springboot annotation.
Controller class
{
#Autowired
B b;
#GetMapping(value = { "/third"})
public String getVariable (){
return b.getInfo();
}
}
#service
B
{
#Autowired
A a;
public String getInfo()
{
return a.getoutput();
}
#repository
interface A extends JpaRepository<Mention your Entity,String>()
{
#procedure(name="Execute your_procedure name")
//return type
public String getoutput();
}
}

Need to pass test case in QC through Java

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.

MongoDB Java driver: Undefined values are not shown

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

Combine for loop and sql in java

I have 2 input dates: myStartDate,myEndDate and a table TEST_TABLE with columns
TEST_ID, TEST_USER,TEST_START, TEST_END
I need to check if the range of dates between myStartDate and myEndDate have corresponding records in the TEST_TABLE.
I also need to ensure that I don't retrieve duplicate records.
Here's a sample of the logic I have so far:
Assuming,
myStartDate=06/06/2012;myEndDate=06/09/2012
int diff = myEndDate - myStartDate; //In this case = 3
String myQuery = "SELECT * FROM TEST_TABLE WHERE"+ myStartDate +"BETWEEN TEST_START AND TEST_END OR "+ (myStartDate +1) +" BETWEEN TEST_START AND TEST_END OR"+ (myStartDate+2)+"BETWEEN TEST_START AND TEST_END OR"+(myStartDate+3)+"BETWEEN TEST_START AND TEST_END";
List <TestTableData> myList = new List();
//Exceute query & save results into myList using add method
Want to know if there's any way to test the range of dates between myStartDate &myEndDate using a for loop in java code, instead of the approach used above in myQuery.Also, how can I avoid duplicates.
New to Java so any help would be appreciated!
Use a ResultSet to iterate over the output, like the code below.
while (res.next()) {
String col1= res.getString("col1");
String col2 = res.getString("col2");
}
If you use an Array implementation , it does not allow for duplicate elements and hence there is no need to check for one.
But if you must use a list then , you could use the following code to remove any duplicate elements.
public static void removeDuplicates(List list)
{
Set set = new HashSet();
List newList = new ArrayList();
for (Iterator iter = list.iterator(); iter.hasNext(); ) {
Object element = iter.next();
if (set.add(element))
newList.add(element);
}
list.clear();
list.addAll(newList);
}
I think what you are asking are some generic questions about how to read a database and how to handle dates in java. I will give you some sample code below. But I suggest you look at the java database tutorial http://docs.oracle.com/javase/tutorial/jdbc/index.html and the java.util.Date api doc http://docs.oracle.com/javase/1.5.0/docs/api/java/sql/Date.html for more info.
Here is some sample code that specifically demonstrates how to implement your question:
// get the input dates
// they are hard coded in this example
// but would probably normally be passed in
String startDateStr = "2/3/03";
String endDateStr = "3/1/03";
// unfortunately, there are 2 "Date" classes in this code and you need to differentiate
// java.util.Date is the standard java class for manipulating dates
// java.sql.Date is used to handle dates in the database
// name conflicts like this are rare in Java
SimpleDateFormat dateFmt = new SimpleDateFormat("M/d/yy");
java.util.Date myStartDate = dateFmt.parse(startDateStr);
java.util.Date myEndDate = dateFmt.parse(endDateStr);
// conneect to the database
// I am using mysql and its driver class is "com.mysql.jdbc.Driver"
// if using a different database, you would use its driver instead
// make sure the jar containing the driver is in your classpath (library list)
// you also have to know the url string that connects to your database
Class.forName("com.mysql.jdbc.Driver").newInstance(); // loads the driver
Connection dbConn = DriverManager.getConnection(
"jdbc:mysql://localhost/testdb", "(db user)", "(db password)"
);
// get the database rows from the db table
// my table is named "testtable"
// my columns are named "DateStart" and "DateEnd"
Statement st = dbConn.createStatement();
String sqlStr = "Select * from testtable";
ResultSet rs = st.executeQuery(sqlStr);
// loop through the rows until you find a row with the right date range
boolean foundRange = false;
while (rs.next()) {
java.util.Date dbStartDate = rs.getDate("DateStart");
java.util.Date dbEndDate = rs.getDate("DateEnd");
if (myStartDate.before(dbStartDate)) continue;
if (myEndDate.after(dbEndDate)) continue;
foundRange = true;
break;
}
if (foundRange) {
// code that executes when range is found in db
} else {
// code that executes if range not found in db
}
dbConn.close();
Hope this helps you get started.

Categories

Resources