error while using groovy.sql Out parameter - stored-procedures

I am trying to execute some stored procedures in groovy way. I am able to do it quite easily by using straight JDBC but this does not seem in the spirit of Grails.
I am trying to call the stored procedure as:
sql.query( "{call web_GetCityStateByZip(?,?,?,?,?)}",[params.postalcode,
sql.out(java.sql.Types.VARCHAR), sql.out(java.sql.Types.VARCHAR),
sql.out(java.sql.Types.INTEGER), sql.out(java.sql.Types.VARCHAR)]) { rs ->
params.city = rs.getString(2)
params.state = rs.getString(3)
}
I tried various ways like sql.call. I was trying to get output variable value after this.
Everytime error:
Message: Cannot register out parameter.
Caused by: java.sql.SQLException: Cannot register out parameter.
Class: SessionExpirationFilter
but this does not seem to work.
Can anyone point me in the right direction?

This is still unanswered, so I did a bit of digging although I don't fully understand the problem. The following turned up from the Groovy source, perhaps it's of some help:
This line seems to be the origin of the exception:
http://groovy.codehaus.org/xref/groovy/sql/Sql.html#1173
This would seem to indicate that you have a Statement object implementing PreparedStatement, when you need the subinterface CallableStatement, which has the registerOutParameter() method which should be ultimately invoked.

Thanks Internet Friend,
If i write code like-
Sql sql = new Sql(dataSource)
Connection conn
ResultSet rs
try {
conn = sql.createConnection()
CallableStatement callable = conn.prepareCall(
"{call web_GetCityStateByZip(?,?,?,?,?)}")
callable.setString("#p_Zip",params.postalcode)
callable.registerOutParameter("#p_City",java.sql.Types.VARCHAR)
callable.registerOutParameter("#p_State",java.sql.Types.VARCHAR)
callable.registerOutParameter("#p_RetCode",java.sql.Types.INTEGER)
callable.registerOutParameter("#p_Msg",java.sql.Types.VARCHAR)
callable.execute()
params.city = callable.getString(2)
params.state = callable.getString(3)
}
It working well in JDBC way. But i wanted to try it like the previous code using sql.query/sql.call.
Any comments??
Thanks
Sadhna

groovy way could be this code:
def getHours(java.sql.Date date, User user) throws CallProceduresServiceException {
log.info "Calling stored procedure for getting hours statistics."
def procedure
def hour
try {
def sql = Sql.newInstance(dataSource.url, user.username, user.password, dataSource.driverClassName)
log.debug "Date(first param): '${date}'"
procedure = "call ${dbPrefixName}.GK_WD_GET_SCHEDULED_TIME_SUM(?, ?, ?, ?)"
log.debug "procedure: ${procedure}"
sql.call("{${procedure}}", [date, Sql.out(Sql.VARCHAR.getType()), Sql.out(Sql.VARCHAR.getType()), Sql.out(Sql.VARCHAR.getType())]) {
hourInDay, hourInWeek, hourInMonth ->
log.debug "Hours in day: '${hourInDay}'"
log.debug "Hours in week: '${hourInWeek}'"
log.debug "Hours in month: '${hourInMonth}'"
hour = new Hour(hourInDay, hourInWeek, hourInMonth)
}
log.info "Procedure was executed."
}
catch (SQLException e) {
throw new CallProceduresServiceException("Executing sql procedure failed!"
+ "\nProcedure: ${procedure}", e)
}
return hour
}
In my app it works great.
Tomas Peterka

Related

Reuse Serilog Templates

Sometimes I need to save the log message to a database.
Getting redundant code like this.
public async Task Timeout(StartSendTradeSaga state, IMessageHandlerContext context)
{
var msg = $"Stale trade: Trade {Data.TradeId} has been awaiting reply for more than one hour";
Log.Error("Stale trade: Trade {TradeId} has been awaiting reply for more than one hour", Data.TradeId);
Data.LogStatus = LogStatus.Error;
Data.LogMessage = msg;
if (Data.SaharaLogId != -1)
{
await SaveLog();
MarkAsComplete();
}
else
{
throw new Exception("Unable to write log to database - missing audit trail id");
}
}
To create the msg I use string interpolation and in the next line I log using the Serilog template syntax.
I log to EleaticSearch in json format. So, I can't use interplolation here.
Looking for suggestions on how to only write the message once.

Connecting to Neo4j Aura with .NET Core 2.2 web api

I am trying to connect a to Neo4j Aura instance from a .NET core 2.2 web api. I understand I need the Neo4j .Net Driver v4.0.0-alpha01, but I do not seem to be able to connect. There aren't very many examples out there as this driver is new and so is Aura.
I keep getting:
Failed after retried for 6 times in 30000 ms. Make sure that your database is online and retry again.
I configure the driver as such
public void ConfigureServices(IServiceCollection services)
{
string uri = "neo4j://1234567.databases.neo4j.io:7687";//not actual subdomain
string username = "neo4j";
string password = "seeeeeeecret";//not actual password
services.AddCors();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddSingleton(GraphDatabase.Driver(uri, AuthTokens.Basic(username, password)));
}
and in my test controller i run this
private async Task<string> Neo4JTestAsync()
{
string db = "MyDb";
string message = "TESTMESSAGE";
IAsyncSession session = _driver.AsyncSession(o => o.WithDatabase(db));
try
{
var greeting = session.WriteTransactionAsync(async tx =>
{
var result = tx.RunAsync("CREATE (a:Greeting) " +
"SET a.message = $message " +
"RETURN a.message + ', from node ' + id(a)",
new { message });
var res = await result;
return "return something eventually";
});
return await greeting;
}
catch (Exception e)
{
return e.Message; // throws "Failed after retried for 6 times in 30000 ms. Make sure that your database is online and retry again"
}
finally
{
await session.CloseAsync();
}
}
I can't get the exact error message you do - but I'm pretty sure this is due to encryption - one of the big differences between the 1.x and 4.x drivers is the default position on Encryption - which is now off by default.
So you'll want to change your initialisation to:
services.AddSingleton(GraphDatabase.Driver(uri, AuthTokens.Basic(username, password), config => config.WithEncryptionLevel(EncryptionLevel.Encrypted)));
That should get you going. Also - make sure you stick with the neo4j:// protocol, as that'll route you properly.
Have you tried bolt:// in the connection string?
string uri = "bolt://1234567.databases.neo4j.io:7687";//not actual subdomain

How to resolve 'groovy.lang.MissingMethodException' ...Possible solutions: notify(), render(java.lang.String)

I am very new to Groovy and this is an old application where the author is no longer with our organization. None of the previous questions that look similar offered any help. The application needs to send a simple message to the user to warn they are missing an entry before they con continue on.
I have made no fewer than 20 changes from flash.message to confirm. Flash causes the application to jump all the way to the user login function. This confirm is giving a crash message: Error 500: Executing action [submitrequest] of controller [SdrmController] caused exception: Runtime error executing action
def submitrequest = {
def testChecker
testChecker = [params.fullExpName].flatten().findAll { it != null }
log.info('testChecker.size = ' + testChecker.size)
if (testChecker.size > 0) {
if (!confirm('Submitting can not be undone, are you sure?')) return
} else {
if (!confirm('You have to pick an expedition. Please return to your Request and pick at least one expedition.')) return
} else {
return
}
}
// rest of long time working code here
}
Expected Result is a simple message to screen tell the user to pick an "Expedition" from a list and then the code returns to the same point so the user can make the change then hit the submit again.
Then full message:
No signature of method: SdrmController.confirm() is applicable for argument types: (java.lang.String) values: [You have to pick an expedition. Please return to your Request and pick at least one expedition.] Possible solutions: notify(), render(java.lang.String)
-- flash.message worked for our situation.
`legChecker = [params.programLeg].flatten().findAll{it!=null}
if(requestInstance.futurePast == "future" && expChecker.size<1) {
flash.message = " you must select a future expedition "
render(view: 'stepstart', model: [....])
return
}`

Graphaware neo4j-php-client | Cannot catch Neo4jException

I'm using Postgresql + Neo4j for my project. I need to rollback postgres queries if neo4j query has failed. So, I need to catch Neo4jException in my code. But couldn't done yet. Thanks for help.
require_once('pgconnect.php');
try{
$conn->beginTransaction();
//some pgsql code
$conn->commit();
require_once('neoconnect.php');
$result = $client->run("a query");
$conn = null;
}
catch(PDOException $e){
require_once('pgrollback.php');
}
this is my working code. But as you can see I don't have a catch block to catch neo4j exception. So I added this but no luck. also tried withNeo4jExceptionInterface as exception class (desperate times). (BTW I'm using wrong typed query to get exception)
catch(Neo4jException $ex){
//done smth
}
Also tried to do this without luck too.
$client->run("a query") or throw new Neo4jException();
I just tested and I have no issues catching an exception, can you maybe provide more code, what is in neoconnect.php for example ?
This is my test :
$client = ClientBuilder::create()
->addConnection('default', 'http://localhost:7474')
->build();
$query = 'INVALID QUERY';
try {
$result = $client->run($query);
} catch (\GraphAware\Neo4j\Client\Exception\Neo4jException $e) {
echo sprintf('Catched exception, message is "%s"', $e->getMessage());
}
-
ikwattro#graphaware ~/d/g/p/neo4j-php-client> php test.php
Catched exception, message is "Invalid input 'I': expected <init> (line 1, column 1 (offset: 0))
"INVALID QUERY"
^"⏎

neo4j 2.0 findNodesByLabelAndProperty not working

I'm currently trying the Neo4j 2.0.0 M3 and see some strange behaviour. In my unit tests, everything works as expected (using an newImpermanentDatabase) but in the real thing, I do not get results from the graphDatabaseService.findNodesByLabelAndProperty.
Here is the code in question:
ResourceIterator<Node> iterator = graphDB
.findNodesByLabelAndProperty(Labels.User, "EMAIL_ADDRESS", emailAddress)
.iterator();
try {
if (iterator.hasNext()) { // => returns false**
return iterator.next();
}
} finally {
iterator.close();
}
return null;
This returns no results. However, when running the following code, I see my node is there (The MATCH!!!!!!!!! is printed) and I also have an index setup via the schema (although that if I read the API, this seems not necessary but is important for performance):
ResourceIterator<Node> iterator1 = GlobalGraphOperations.at(graphDB).getAllNodesWithLabel(Labels.User).iterator();
while (iterator1.hasNext()) {
Node result = iterator1.next();
UserDao.printoutNode(emailAddress, result);
}
And UserDao.printoutNode
public static void printoutNode(String emailAddress, Node next) {
System.out.print(next);
ResourceIterator<Label> iterator1 = next.getLabels().iterator();
System.out.print("(");
while (iterator1.hasNext()) {
System.out.print(iterator1.next().name());
}
System.out.print("): ");
for(String key : next.getPropertyKeys()) {
System.out.print(key + ": " + next.getProperty(key).toString() + "; ");
if(emailAddress.equals( next.getProperty(key).toString())) {
System.out.print("MATCH!!!!!!!!!");
}
}
System.out.println();
}
I already debugged through the code and what I already found out is that I pass via the InternalAbstractGraphDatabase.map2Nodes to a DelegatingIndexProxy.getDelegate and end up in IndexReader.Empty class which returns the IteratorUtil.EMPTY_ITERATOR thus getting false for iterator.hasNext()
Any idea's what I am doing wrong?
Found it:
I only included neo4j-kernel:2.0.0-M03 in the classpath. The moment I added neo4j-cypher:2.0.0-M03 all was working well.
Hope this answer helps save some time for other users.
#Neo4j: would be nice if an exception would be thrown instead of just returning nothing.
#Ricardo: I wanted to but I was not allowed yet as my reputation wasn't good enough as a new SO user.

Resources