Fw: Re: [Lucee] Re: can't use different connections to the same datasource inside a single transaction

OK. I see now. This error probably needs to be thrown, since the logistics of managing transactions through multiple connections is the responsibility of the driver and isn’t guaranteed - not to mention row locking issues which may arise. Just because it works in ACF doesn’t mean it, necessarily, should work. :slight_smile:

In either case, why don’t you just thread the code in your logging and then you won’t have to worry about the transaction used in the primary thread?

JonOn April 25, 2016 at 6:34:15 PM, Puritan Paul (@Puritan_Paul) wrote:

Here’s the stack trace I’m getting:

{
“ERROR”: “can’t use different connections to the same datasource inside a single transaction”,
“DETAIL”: “”,
“TAGCONTEXT”: “/Users/jonathanprice/Websites/Lucee/lucee-4.5.2.018-express/webapps/ROOT/EM2/model/services/object.cfc [Line 8]”,
“STACKTRACE”: [
{
“Raw_Trace”: “model.services.object_cfc$cf.udfCall(/Users/jonathanprice/Websites/Lucee/lucee-4.5.2.018-express/webapps/ROOT/EM2/model/services/object.cfc:8)”,
“codePrintPlain”: “6: \n7: public struct function get( required numeric id, required string name ) {\n8: local.obj = entityLoad(’#arguments.name#’, #arguments.id#, true);\n9: \n10: if (!isDefined(‘local.obj’) )\n”,
“column”: 0,
“line”: 8,
“template”: “/Users/jonathanprice/Websites/Lucee/lucee-4.5.2.018-express/webapps/ROOT/EM2/model/services/object.cfc”,
“id”: “??”,
“type”: “cfml”,
“codePrintHTML”: “6:
\n7: public struct function get( required numeric id, required string name ) {
\n8: local.obj = entityLoad(’#arguments.name#’, #arguments.id#, true);
\n9:
\n10: if (!isDefined(‘local.obj’) )
\n”
},
{
“Raw_Trace”: “model.services.authentication_cfc$cf.udfCall(/Users/jonathanprice/Websites/Lucee/lucee-4.5.2.018-express/webapps/ROOT/EM2/model/services/authentication.cfc:21)”,
“codePrintPlain”: “19: logAuthenticationRequest( username = arguments.username, password = arguments.password, deviceId = arguments.deviceId, status = false, message = error );\n20: } else {\n21: var user = object.get( name = ‘User’, id = authenticate.UserId );\n22: // writeDump(user);\n23: user.init();\n”,
“column”: 0,
“line”: 21,
“template”: “/Users/jonathanprice/Websites/Lucee/lucee-4.5.2.018-express/webapps/ROOT/EM2/model/services/authentication.cfc”,
“id”: “??”,
“type”: “cfml”,
“codePrintHTML”: “19: logAuthenticationRequest( username = arguments.username, password = arguments.password, deviceId = arguments.deviceId, status = false, message = error );
\n20: } else {
\n21: var user = object.get( name = ‘User’, id = authenticate.UserId );
\n22: // writeDump(user);
\n23: user.init();
\n”
},
{
“Raw_Trace”: “authentication_cfc$cf.udfCall(/Users/jonathanprice/Websites/Lucee/lucee-4.5.2.018-express/webapps/ROOT/EM2/api/rest/resources/authentication.cfc:8)”,
“codePrintPlain”: “6: transaction {\n7: try {\n8: var status = variables.authSvc.login(username = arguments.username, password = arguments.password, deviceId = arguments.deviceId );\n9: transaction action=“commit”;\n10: }\n”,
“column”: 0,
“line”: 8,
“template”: “/Users/jonathanprice/Websites/Lucee/lucee-4.5.2.018-express/webapps/ROOT/EM2/api/rest/resources/authentication.cfc”,
“id”: “??”,
“type”: “cfml”,
“codePrintHTML”: “6: transaction {
\n7: try {
\n8: var status = variables.authSvc.login(username = arguments.username, password = arguments.password, deviceId = arguments.deviceId );
\n9: transaction action=“commit”;
\n10: }
\n”
},
{
“Raw_Trace”: “core.api_cfc$cf.udfCall1(/Users/jonathanprice/Websites/Taffy/atuttle-Taffy-75b0912/core/api.cfc:338)”,
“codePrintPlain”: “336: \t\t\t\t\t\tmethod=”#_taffyRequest.method#"\n337: \t\t\t\t\t\targumentcollection="#_taffyRequest.requestArguments#"\n338: \t\t\t\t\t\treturnvariable="_taffyRequest.result"\n339: \t\t\t\t\t/>\n340: \t\t\t\t\t\n",
“column”: 0,
“line”: 338,
“template”: “/Users/jonathanprice/Websites/Taffy/atuttle-Taffy-75b0912/core/api.cfc”,
“id”: “??”,
“type”: “cfml”,
“codePrintHTML”: “336: \t\t\t\t\t\tmethod=”#_taffyRequest.method#"
\n337: \t\t\t\t\t\targumentcollection="#_taffyRequest.requestArguments#"
\n338: \t\t\t\t\t\treturnvariable="_taffyRequest.result"
\n339: \t\t\t\t\t/>
\n340: \t\t\t\t\t<cfset m.afterResource = getTickCount() />
\n"
}
]
}

On Apr 25, 2016, at 3:31 PM, Jon Clausen <@Jon_Clausen> wrote:

Jonathan,

What, specifically, is the error message that’s being thrown? Without that, I’d have no idea what to tell you.

Lucee does maintain separate connection pools for ORM/Hibernate and CF queries, which may have something to do with what you’re seeing.

Jon

On April 25, 2016 at 6:02:43 PM, Jonathan Price (@Puritan_Paul) wrote:

FWIW I’ve verified that this same code runs in ACF10 locally. Bummed, because we really wanted to use Lucee for a new project, but I’ve already hit upon this oddity.

Also, I hadn’t included the code calling the login function in the original post. It’s within a Taffy resource and looks like this. Not much going on.

public function post(required string username, required string password, required string deviceId ) {
    transaction {
        try {
            var status = variables.authSvc.login(username = arguments.username, password = arguments.password, deviceId = arguments.deviceId );
            transaction action="commit";
        }
        catch( any e ) {
            transaction action="rollback";
            rethrow;
        }
    }

    if ( status.isError() )
        return noData().withStatus(401, status.getMessage() );
    else
        return noData().withStatus(200, status.getMessage() );

}

On Monday, April 25, 2016 at 1:08:12 PM UTC-7, Jonathan Price wrote:
I’m not entirely sure why this is problematic - hoping someone can clarify what I’m doing wrong here. When I call the login function below (with a valid username/pw combo), I’m getting the error in the title. The error line number points to the ‘var req = object.getNew(‘AuthenticationRequest’);’ line in the logAuthenticationRequest function. FWIW, object.getNew() is just a wrapper for entityNew in this context. I’m pretty sure I’ve done this type of thing in ACF10. Any suggestions/explanations?


component accessors=“true” {

property object;
property datetime;

public any function login( required string username, required string password, required string deviceId ) {
    var authenticate = authenticateUser( argumentCollection = arguments );
    var error = '';
    var status = object.getNew( name = 'ReturnStatus', np = true);

    if ( authenticate.RecordCount != 1 )
        error = 'Username and password do not match.'

    if (deviceID == '')
        error = 'Invalid device id.'

    if ( error != '' ) {
        status.error().setMessage( error );
        logAuthenticationRequest( username = arguments.username, password = arguments.password, deviceId = arguments.deviceId, status = false, message = error );
    } else {
        var user = object.get( name = 'User', id = authenticate.UserId );
        user.init();
        user.updateAuthenticationToken( deviceId = arguments.deviceId );
        user.save();
        
        status.success().setDetails( {userId: authenticate.UserId} );
    }

    return status;
}

public any function authenticateUser( required string username, required string password ) {

    local.queryService = new query(); 
    local.queryService.setName("validateUser"); 
    local.queryService.addParam( name = "username", value = arguments.username, cfsqltype = "cf_sql_varchar" ); 
    local.queryService.addParam( name = "unhashedPassword", value = arguments.password, cfsqltype = "cf_sql_varchar" ); 
    local.queryService.addParam( name = "hashedPassword", value = Hash(arguments.password, 'SHA'), cfsqltype = "cf_sql_varchar" );

    local.sql = "
        SELECT
            a.UserID,
            a.UserName,
            a.TempPassword,
            a.FirstName,
            a.LastName,
            IF( a.TempPassword = :unhashedPassword, 1, 0) AS TemporaryLogin
        FROM
            User a
        WHERE
            1 = 1
            AND (
                a.UserName = :username
            )
            AND (
                a.Password = :hashedPassword
                OR a.TempPassword = :unhashedPassword
            );
    ";

    local.queryService.setSql( local.sql );
    local.result = queryService.execute( sql = local.sql );

    return local.result.getResult();
}

public any function logAuthenticationRequest( 
    required string username, 
    required string password, 
    required string deviceId, 
    required boolean status, 
    required string message ) 
{
    var req = object.getNew('AuthenticationRequest');
    
    arguments.createdDate = datetime.getNow();

    if ( req.populate( context = arguments ).validate() )
        req.save();
}

}


Love Lucee? Become a supporter and be part of the Lucee project today! - http://lucee.org/supporters/become-a-supporter.html

You received this message because you are subscribed to the Google Groups “Lucee” group.
To unsubscribe from this group and stop receiving emails from it, send an email to lucee+unsubscribe@googlegroups.com.
To post to this group, send email to lucee@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/lucee/c4ae96aa-bc63-404a-a951-e9fd4fffba1b%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Love Lucee? Become a supporter and be part of the Lucee project today! - http://lucee.org/supporters/become-a-supporter.html

You received this message because you are subscribed to a topic in the Google Groups “Lucee” group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/lucee/OOtXwK3pMpc/unsubscribe.
To unsubscribe from this group and all its topics, send an email to lucee+unsubscribe@googlegroups.com.
To post to this group, send email to lucee@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/lucee/etPan.571e9acc.5bcb9c71.31c%40jonclausen-mbp.local.
For more options, visit https://groups.google.com/d/optout.


Love Lucee? Become a supporter and be part of the Lucee project today! - http://lucee.org/supporters/become-a-supporter.html

You received this message because you are subscribed to the Google Groups “Lucee” group.
To unsubscribe from this group and stop receiving emails from it, send an email to lucee+unsubscribe@googlegroups.com.
To post to this group, send email to lucee@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/lucee/187D91CE-B352-47F4-B87D-0942560C68EE%40gmail.com.
For more options, visit https://groups.google.com/d/optout.