Can't use different connections to the same datasource inside a single transaction

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();
}

}

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();
}

}

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.

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 mailto: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 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 mailto:lucee+unsubscribe@googlegroups.com.
To post to this group, send email to lucee@googlegroups.com mailto: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 https://groups.google.com/d/msgid/lucee/c4ae96aa-bc63-404a-a951-e9fd4fffba1b%40googlegroups.com?utm_medium=email&utm_source=footer.
For more options, visit https://groups.google.com/d/optout 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 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 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 mailto:lucee+unsubscribe@googlegroups.com.
To post to this group, send email to lucee@googlegroups.com mailto: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 https://groups.google.com/d/msgid/lucee/etPan.571e9acc.5bcb9c71.31c%40jonclausen-mbp.local?utm_medium=email&utm_source=footer.
For more options, visit https://groups.google.com/d/optout https://groups.google.com/d/optout.

Depends on if you are within a transaction when you perform that validation. The issue, from what I can see, is that you are running into is that you are within an open transaction block when you attempt to run those additional validation queries.

It’s really a processing flow issue and the solution is to perform your validation first before you enter the transactional state or to use ORM methods in your validation so that the ORM session state is consistent, along with the connection.

Ideally, you’ve ensured the record you are about to persist meets all of your validation requirements before you open that transaction up.

JonOn April 26, 2016 at 3:23:30 PM, Puritan Paul (@Puritan_Paul) wrote:

Okay, so this is turning into a broader issue that I’m unclear about how to handle. I often use a query to validate some condition, like the existence of a record (as opposed to entityload). I usually use ORM objects to persist to the DB. So, it’s pretty common for a service function to call both - which seems to be a problem in Lucee? Or maybe it should be a problem in ACF and isn’t - regardless, it’s a fairly customary practice in some apps I’ve worked on.

Is this really that unusual? If not, how are people handling it? Starting separate threads feels like overkill, especially having to handle them asynchronously.

Or do people really not do both?

On Apr 26, 2016, at 10:03 AM, Puritan Paul <@Puritan_Paul> wrote:

I’ve got zero threading experience, so it’s time to do some reading. Thanks for the suggestions.

On Apr 26, 2016, at 4:41 AM, Jon Clausen <@Jon_Clausen> wrote:

Hi Paul,

I meant start a separate thread for your logging using cfthread. Something like:

public any function logAuthenticationRequest(
required string username,
required string password,
required string deviceId,
required boolean status,
required string message
)
{

var threadName = "logAuthenticationRequest_" & createUUID();
      
thread name="#threadName#" action="run"
    object=object
    arguments=arguments
{
    var req = object.getNew('AuthenticationRequest');
  
    arguments.createdDate = datetime.getNow();

    if ( req.populate( context = arguments ).validate() )
        req.save();
  
}
  
return cfthread[ threadName ];

}

Debugging thread errors is a bit more involved, but logging is an example of when they can come in really handy.

On April 25, 2016 at 9:22:35 PM, Puritan Paul (@Puritan_Paul) wrote:

On Apr 25, 2016, at 5:18 PM, Jon Clausen <@Jon_Clausen> wrote:

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:

Yep, I figured that might be the case. Wouldn’t surprise me at all if I were approaching incorrectly. Just hoping to figure out what I’m doing incorrectly, if that’s the case.

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?

Mostly because I’m not sure what that means :slight_smile: Do you mean put a transaction inside the logging function itself as opposed to wrap the entire thing in a transaction?

Jon


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.571f53d0.713bc17a.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/53ACAAD2-78B0-46CA-9D0F-093ADFA0A0A0%40gmail.com.
For more options, visit https://groups.google.com/d/optout.

Right, this makes sense. Sounds like I’ve just gotten away with some laziness up to now.

I removed the outer transaction call and pushed it into the service function like so:

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 );
    } else {

        transaction {
            try {
                var user = object.get( name = 'User', id = authenticate.UserId );
                user
                    .updateAuthenticationToken( deviceId = arguments.deviceId )
                    .save();

                status.success().setDetails( {token: user.getAuthenticationTokenByDevice( deviceId = arguments.deviceId )} );
                transaction action="commit";            
            }
            catch( any e ) {
                transaction action="rollback";
                rethrow;
            }
        }
        
    }

    logAuthenticationRequest( 
        username = arguments.username, 
        password = arguments.password, 
        deviceId = arguments.deviceId, 
        status = status.isValid(), 
        message = error );

    return status;
}

And now I’m getting some kind of StackOverflow error. But maybe it’s a Taffy issue? I can’t really tell. Thanks a lot for all your help.

An unhandled exception occurred: java.lang.StackOverflowError –
ERROR WHEN LOGGING EXCEPTION
Catch

additional Struct

Detail 
    string 
ErrNumber 
    number 0 
ErrorCode 
    string 0 
Extended_Info 
    string 
ExtendedInfo 
    string 
Message 
    string Element at position [1] doesn't exist in array 
StackTrace 
    string Element at position [1] doesn't exist in array
at lucee.runtime.type.ArrayImpl.invalidPosition(ArrayImpl.java:194):194
at lucee.runtime.type.ArrayImpl.getE(ArrayImpl.java:171):171
at lucee.runtime.type.ArrayImpl.get(ArrayImpl.java:124):124
at lucee.runtime.type.util.ArraySupport.get(ArraySupport.java:314):314
at lucee.runtime.util.VariableUtilImpl.get(VariableUtilImpl.java:255):255
at lucee.runtime.util.VariableUtilImpl.getCollection(VariableUtilImpl.java:249):249
at lucee.runtime.PageContextImpl.getCollection(PageContextImpl.java:1416):1416
at core.api_cfc$cf.udfCall1(/Users/jonathanprice/Websites/Taffy/atuttle-Taffy-75b0912/core/api.cfc:163):163
at core.api_cfc$cf.udfCall(/Users/jonathanprice/Websites/Taffy/atuttle-Taffy-75b0912/core/api.cfc):-1
at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:111):111
at lucee.runtime.type.UDFImpl._call(UDFImpl.java:328):328
at lucee.runtime.type.UDFImpl.call(UDFImpl.java:229):229
at lucee.runtime.ComponentImpl._call(ComponentImpl.java:642):642
at lucee.runtime.ComponentImpl._call(ComponentImpl.java:524):524
at lucee.runtime.ComponentImpl.call(ComponentImpl.java:1761):1761
at lucee.runtime.listener.ModernAppListener.call(ModernAppListener.java:405):405
at lucee.runtime.listener.ModernAppListener.onError(ModernAppListener.java:392):392
at lucee.runtime.PageContextImpl.execute(PageContextImpl.java:2273):2273
at lucee.runtime.PageContextImpl.execute(PageContextImpl.java:2225):2225
at lucee.runtime.engine.CFMLEngineImpl.serviceCFML(CFMLEngineImpl.java:456):456
at lucee.loader.servlet.CFMLServlet.service(CFMLServlet.java:47):47
at javax.servlet.http.HttpServlet.service(HttpServlet.java:725):725
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291):291
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206):206
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52):52
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239):239
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206):206
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219):219
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106):106
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501):501
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142):142
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79):79
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610):610
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88):88
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:537):537
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1085):1085
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:658):658
at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:222):222
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1556):1556
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1513):1513
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142):1142
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617):617
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61):61
at java.lang.Thread.run(Thread.java:745):745

TagContext Array

    1 Struct

        codePrintHTML 
            string 161: 				</cfif>

162: <cfif structKeyExists(root,“tagContext”)>

163: <cfset data.tagContext = root.tagContext[1].template & " [Line #root.tagContext[1].line#]" />

164:

165: <!— MAKE IT LOOK GOOD! —>

        codePrintPlain 
            string 161: 				

162:
163:
164:
165:

        column 
            number 0 
        id 
            string ?? 
        line 
            number 163 
        Raw_Trace 
            string core.api_cfc$cf.udfCall1(/Users/jonathanprice/Websites/Taffy/atuttle-Taffy-75b0912/core/api.cfc:163) 
        template 
            string /Users/jonathanprice/Websites/Taffy/atuttle-Taffy-75b0912/core/api.cfc 
        type 
            string cfml 
type 
    string expression> On Apr 26, 2016, at 2:31 PM, Jon Clausen <@Jon_Clausen> wrote:

Depends on if you are within a transaction when you perform that validation. The issue, from what I can see, is that you are running into is that you are within an open transaction block when you attempt to run those additional validation queries.

It’s really a processing flow issue and the solution is to perform your validation first before you enter the transactional state or to use ORM methods in your validation so that the ORM session state is consistent, along with the connection.

Ideally, you’ve ensured the record you are about to persist meets all of your validation requirements before you open that transaction up.

Jon

On April 26, 2016 at 3:23:30 PM, Puritan Paul (@Puritan_Paul mailto:Puritan_Paul) wrote:

Okay, so this is turning into a broader issue that I’m unclear about how to handle. I often use a query to validate some condition, like the existence of a record (as opposed to entityload). I usually use ORM objects to persist to the DB. So, it’s pretty common for a service function to call both - which seems to be a problem in Lucee? Or maybe it should be a problem in ACF and isn’t - regardless, it’s a fairly customary practice in some apps I’ve worked on.

Is this really that unusual? If not, how are people handling it? Starting separate threads feels like overkill, especially having to handle them asynchronously.

Or do people really not do both?

On Apr 26, 2016, at 10:03 AM, Puritan Paul <@Puritan_Paul mailto:Puritan_Paul> wrote:

I’ve got zero threading experience, so it’s time to do some reading. Thanks for the suggestions.

On Apr 26, 2016, at 4:41 AM, Jon Clausen <@Jon_Clausen mailto:Jon_Clausen> wrote:

Hi Paul,

I meant start a separate thread for your logging using cfthread. Something like:

public any function logAuthenticationRequest(
required string username,
required string password,
required string deviceId,
required boolean status,
required string message
)
{

var threadName = "logAuthenticationRequest_" & createUUID();
      
thread name="#threadName#" action="run"
    object=object
    arguments=arguments
{
    var req = object.getNew('AuthenticationRequest');
  
    arguments.createdDate = datetime.getNow();

    if ( req.populate( context = arguments ).validate() )
        req.save();
  
}
  
return cfthread[ threadName ];

}

Debugging thread errors is a bit more involved, but logging is an example of when they can come in really handy.

On April 25, 2016 at 9:22:35 PM, Puritan Paul (@Puritan_Paul mailto:Puritan_Paul) wrote:

On Apr 25, 2016, at 5:18 PM, Jon Clausen <@Jon_Clausen mailto:Jon_Clausen> wrote:

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:

Yep, I figured that might be the case. Wouldn’t surprise me at all if I were approaching incorrectly. Just hoping to figure out what I’m doing incorrectly, if that’s the case.

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?

Mostly because I’m not sure what that means :slight_smile: Do you mean put a transaction inside the logging function itself as opposed to wrap the entire thing in a transaction?

Jon


Love Lucee? Become a supporter and be part of the Lucee project today! - http://lucee.org/supporters/become-a-supporter.html 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 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 mailto:lucee+unsubscribe@googlegroups.com.
To post to this group, send email to lucee@googlegroups.com mailto:lucee@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/lucee/etPan.571f53d0.713bc17a.31c%40jonclausen-mbp.local https://groups.google.com/d/msgid/lucee/etPan.571f53d0.713bc17a.31c%40jonclausen-mbp.local?utm_medium=email&utm_source=footer.
For more options, visit https://groups.google.com/d/optout 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 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 mailto:lucee+unsubscribe@googlegroups.com.
To post to this group, send email to lucee@googlegroups.com mailto:lucee@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/lucee/53ACAAD2-78B0-46CA-9D0F-093ADFA0A0A0%40gmail.com https://groups.google.com/d/msgid/lucee/53ACAAD2-78B0-46CA-9D0F-093ADFA0A0A0%40gmail.com?utm_medium=email&utm_source=footer.
For more options, visit https://groups.google.com/d/optout 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 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 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 mailto:lucee+unsubscribe@googlegroups.com.
To post to this group, send email to lucee@googlegroups.com mailto:lucee@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/lucee/etPan.571fde25.84bd528.31c%40jonclausen-mbp.local https://groups.google.com/d/msgid/lucee/etPan.571fde25.84bd528.31c%40jonclausen-mbp.local?utm_medium=email&utm_source=footer.
For more options, visit https://groups.google.com/d/optout https://groups.google.com/d/optout.

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:

Yep, I figured that might be the case. Wouldn’t surprise me at all if I were approaching incorrectly. Just hoping to figure out what I’m doing incorrectly, if that’s the case.

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?

Mostly because I’m not sure what that means :slight_smile: Do you mean put a transaction inside the logging function itself as opposed to wrap the entire thing in a transaction?> On Apr 25, 2016, at 5:18 PM, Jon Clausen <@Jon_Clausen> wrote:

Jon

On April 25, 2016 at 6:34:15 PM, Puritan Paul (@Puritan_Paul mailto: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 mailto: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 mailto: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 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 mailto:lucee+unsubscribe@googlegroups.com.
To post to this group, send email to lucee@googlegroups.com mailto: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 https://groups.google.com/d/msgid/lucee/c4ae96aa-bc63-404a-a951-e9fd4fffba1b%40googlegroups.com?utm_medium=email&utm_source=footer.
For more options, visit https://groups.google.com/d/optout 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 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 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 mailto:lucee+unsubscribe@googlegroups.com.
To post to this group, send email to lucee@googlegroups.com mailto: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 https://groups.google.com/d/msgid/lucee/etPan.571e9acc.5bcb9c71.31c%40jonclausen-mbp.local?utm_medium=email&utm_source=footer.
For more options, visit https://groups.google.com/d/optout 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 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 mailto:lucee+unsubscribe@googlegroups.com.
To post to this group, send email to lucee@googlegroups.com mailto: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 https://groups.google.com/d/msgid/lucee/187D91CE-B352-47F4-B87D-0942560C68EE%40gmail.com?utm_medium=email&utm_source=footer.
For more options, visit https://groups.google.com/d/optout 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 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 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 mailto:lucee+unsubscribe@googlegroups.com.
To post to this group, send email to lucee@googlegroups.com mailto:lucee@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/lucee/etPan.571eb3e4.1db92d09.31c%40jonclausen-mbp.local https://groups.google.com/d/msgid/lucee/etPan.571eb3e4.1db92d09.31c%40jonclausen-mbp.local?utm_medium=email&utm_source=footer.
For more options, visit https://groups.google.com/d/optout https://groups.google.com/d/optout.

Hi Paul,

I meant start a separate thread for your logging using cfthread. Something like:

public any function logAuthenticationRequest(
required string username,
required string password,
required string deviceId,
required boolean status,
required string message
)
{

var threadName = "logAuthenticationRequest_" & createUUID();
     
thread name="#threadName#" action="run"
    object=object
    arguments=arguments
{
    var req = object.getNew('AuthenticationRequest');
 
    arguments.createdDate = datetime.getNow();

    if ( req.populate( context = arguments ).validate() )
        req.save();
 
}
 
return cfthread[ threadName ];

}
Debugging thread errors is a bit more involved, but logging is an example of when they can come in really handy.On April 25, 2016 at 9:22:35 PM, Puritan Paul (@Puritan_Paul) wrote:

On Apr 25, 2016, at 5:18 PM, Jon Clausen <@Jon_Clausen> wrote:

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:

Yep, I figured that might be the case. Wouldn’t surprise me at all if I were approaching incorrectly. Just hoping to figure out what I’m doing incorrectly, if that’s the case.

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?

Mostly because I’m not sure what that means :slight_smile: Do you mean put a transaction inside the logging function itself as opposed to wrap the entire thing in a transaction?

Jon

I’ve got zero threading experience, so it’s time to do some reading. Thanks for the suggestions.> On Apr 26, 2016, at 4:41 AM, Jon Clausen <@Jon_Clausen> wrote:

Hi Paul,

I meant start a separate thread for your logging using cfthread. Something like:

public any function logAuthenticationRequest(
required string username,
required string password,
required string deviceId,
required boolean status,
required string message
)
{

var threadName = "logAuthenticationRequest_" & createUUID();
     
thread name="#threadName#" action="run"
    object=object
    arguments=arguments
{
    var req = object.getNew('AuthenticationRequest');
 
    arguments.createdDate = datetime.getNow();

    if ( req.populate( context = arguments ).validate() )
        req.save();
 
}
 
return cfthread[ threadName ];

}
Debugging thread errors is a bit more involved, but logging is an example of when they can come in really handy.

On April 25, 2016 at 9:22:35 PM, Puritan Paul (@Puritan_Paul mailto:Puritan_Paul) wrote:

On Apr 25, 2016, at 5:18 PM, Jon Clausen <@Jon_Clausen mailto:Jon_Clausen> wrote:

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:

Yep, I figured that might be the case. Wouldn’t surprise me at all if I were approaching incorrectly. Just hoping to figure out what I’m doing incorrectly, if that’s the case.

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?

Mostly because I’m not sure what that means :slight_smile: Do you mean put a transaction inside the logging function itself as opposed to wrap the entire thing in a transaction?

Jon


Love Lucee? Become a supporter and be part of the Lucee project today! - http://lucee.org/supporters/become-a-supporter.html 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 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 mailto:lucee+unsubscribe@googlegroups.com.
To post to this group, send email to lucee@googlegroups.com mailto:lucee@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/lucee/etPan.571f53d0.713bc17a.31c%40jonclausen-mbp.local https://groups.google.com/d/msgid/lucee/etPan.571f53d0.713bc17a.31c%40jonclausen-mbp.local?utm_medium=email&utm_source=footer.
For more options, visit https://groups.google.com/d/optout https://groups.google.com/d/optout.

Okay, so this is turning into a broader issue that I’m unclear about how to handle. I often use a query to validate some condition, like the existence of a record (as opposed to entityload). I usually use ORM objects to persist to the DB. So, it’s pretty common for a service function to call both - which seems to be a problem in Lucee? Or maybe it should be a problem in ACF and isn’t - regardless, it’s a fairly customary practice in some apps I’ve worked on.

Is this really that unusual? If not, how are people handling it? Starting separate threads feels like overkill, especially having to handle them asynchronously.

Or do people really not do both?> On Apr 26, 2016, at 10:03 AM, Puritan Paul <@Puritan_Paul> wrote:

I’ve got zero threading experience, so it’s time to do some reading. Thanks for the suggestions.

On Apr 26, 2016, at 4:41 AM, Jon Clausen <@Jon_Clausen mailto:Jon_Clausen> wrote:

Hi Paul,

I meant start a separate thread for your logging using cfthread. Something like:

public any function logAuthenticationRequest(
required string username,
required string password,
required string deviceId,
required boolean status,
required string message
)
{

var threadName = "logAuthenticationRequest_" & createUUID();
     
thread name="#threadName#" action="run"
    object=object
    arguments=arguments
{
    var req = object.getNew('AuthenticationRequest');
 
    arguments.createdDate = datetime.getNow();

    if ( req.populate( context = arguments ).validate() )
        req.save();
 
}
 
return cfthread[ threadName ];

}
Debugging thread errors is a bit more involved, but logging is an example of when they can come in really handy.

On April 25, 2016 at 9:22:35 PM, Puritan Paul (@Puritan_Paul mailto:Puritan_Paul) wrote:

On Apr 25, 2016, at 5:18 PM, Jon Clausen <@Jon_Clausen mailto:Jon_Clausen> wrote:

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:

Yep, I figured that might be the case. Wouldn’t surprise me at all if I were approaching incorrectly. Just hoping to figure out what I’m doing incorrectly, if that’s the case.

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?

Mostly because I’m not sure what that means :slight_smile: Do you mean put a transaction inside the logging function itself as opposed to wrap the entire thing in a transaction?

Jon


Love Lucee? Become a supporter and be part of the Lucee project today! - http://lucee.org/supporters/become-a-supporter.html 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 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 mailto:lucee+unsubscribe@googlegroups.com.
To post to this group, send email to lucee@googlegroups.com mailto:lucee@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/lucee/etPan.571f53d0.713bc17a.31c%40jonclausen-mbp.local https://groups.google.com/d/msgid/lucee/etPan.571f53d0.713bc17a.31c%40jonclausen-mbp.local?utm_medium=email&utm_source=footer.
For more options, visit https://groups.google.com/d/optout https://groups.google.com/d/optout.

Right, this makes sense. Sounds like I’ve just gotten away with some laziness up to now.

I removed the outer transaction call and pushed it into the service function like so:

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 );
    } else {

        transaction {
            try {
                var user = object.get( name = 'User', id = authenticate.UserId );
                user
                    .updateAuthenticationToken( deviceId = arguments.deviceId )
                    .save();

                status.success().setDetails( {token: user.getAuthenticationTokenByDevice( deviceId = arguments.deviceId )} );
                transaction action="commit";            
            }
            catch( any e ) {
                transaction action="rollback";
                rethrow;
            }
        }
        
    }

    logAuthenticationRequest( 
        username = arguments.username, 
        password = arguments.password, 
        deviceId = arguments.deviceId, 
        status = status.isValid(), 
        message = error );

    return status;
}

And now I’m getting some kind of StackOverflow error. But maybe it’s a Taffy issue? I can’t really tell. Thanks a lot for all your help.

An unhandled exception occurred: java.lang.StackOverflowError –
ERROR WHEN LOGGING EXCEPTION
Catch

additional Struct

Detail  
    string  
ErrNumber  
    number 0  
ErrorCode  
    string 0  
Extended_Info  
    string  
ExtendedInfo  
    string  
Message  
    string Element at position [1] doesn't exist in array  
StackTrace  
    string Element at position [1] doesn't exist in array
    at lucee.runtime.type.ArrayImpl.invalidPosition(ArrayImpl.java:194):194
    at lucee.runtime.type.ArrayImpl.getE(ArrayImpl.java:171):171
    at lucee.runtime.type.ArrayImpl.get(ArrayImpl.java:124):124
    at lucee.runtime.type.util.ArraySupport.get(ArraySupport.java:314):314
    at lucee.runtime.util.VariableUtilImpl.get(VariableUtilImpl.java:255):255
    at lucee.runtime.util.VariableUtilImpl.getCollection(VariableUtilImpl.java:249):249
    at lucee.runtime.PageContextImpl.getCollection(PageContextImpl.java:1416):1416
    at core.api_cfc$cf.udfCall1(/Users/jonathanprice/Websites/Taffy/atuttle-Taffy-75b0912/core/api.cfc:163):163
    at core.api_cfc$cf.udfCall(/Users/jonathanprice/Websites/Taffy/atuttle-Taffy-75b0912/core/api.cfc):-1
    at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:111):111
    at lucee.runtime.type.UDFImpl._call(UDFImpl.java:328):328
    at lucee.runtime.type.UDFImpl.call(UDFImpl.java:229):229
    at lucee.runtime.ComponentImpl._call(ComponentImpl.java:642):642
    at lucee.runtime.ComponentImpl._call(ComponentImpl.java:524):524
    at lucee.runtime.ComponentImpl.call(ComponentImpl.java:1761):1761
    at lucee.runtime.listener.ModernAppListener.call(ModernAppListener.java:405):405
    at lucee.runtime.listener.ModernAppListener.onError(ModernAppListener.java:392):392
    at lucee.runtime.PageContextImpl.execute(PageContextImpl.java:2273):2273
    at lucee.runtime.PageContextImpl.execute(PageContextImpl.java:2225):2225
    at lucee.runtime.engine.CFMLEngineImpl.serviceCFML(CFMLEngineImpl.java:456):456
    at lucee.loader.servlet.CFMLServlet.service(CFMLServlet.java:47):47
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:725):725
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291):291
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206):206
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52):52
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239):239
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206):206
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219):219
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106):106
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501):501
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142):142
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79):79
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610):610
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88):88
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:537):537
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1085):1085
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:658):658
    at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:222):222
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1556):1556
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1513):1513
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142):1142
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617):617
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61):61
    at java.lang.Thread.run(Thread.java:745):745

TagContext Array

    1 Struct

        codePrintHTML  
            string 161:                             </cfif>

162: <cfif structKeyExists(root,“tagContext”)>
163: <cfset data.tagContext = root.tagContext[1].template & " [Line #root.tagContext[1].line#]" />
164:
165: <!— MAKE IT LOOK GOOD! —>

        codePrintPlain  
            string 161:                              

162:
163:
164:
165:

        column  
            number 0  
        id  
            string ??  
        line  
            number 163  
        Raw_Trace  
            string core.api_cfc$cf.udfCall1(/Users/jonathanprice/Websites/Taffy/atuttle-Taffy-75b0912/core/api.cfc:163)  
        template  
            string /Users/jonathanprice/Websites/Taffy/atuttle-Taffy-75b0912/core/api.cfc  
        type  
            string cfml  
type  
    string expressionOn April 26, 2016 at 6:36:22 PM, Puritan Paul (@Puritan_Paul) wrote:

On Apr 26, 2016, at 2:31 PM, Jon Clausen <@Jon_Clausen> wrote:

Depends on if you are within a transaction when you perform that validation. The issue, from what I can see, is that you are running into is that you are within an open transaction block when you attempt to run those additional validation queries.

It’s really a processing flow issue and the solution is to perform your validation first before you enter the transactional state or to use ORM methods in your validation so that the ORM session state is consistent, along with the connection.

Ideally, you’ve ensured the record you are about to persist meets all of your validation requirements before you open that transaction up.

Jon

On April 26, 2016 at 3:23:30 PM, Puritan Paul (@Puritan_Paul) wrote:

Okay, so this is turning into a broader issue that I’m unclear about how to handle. I often use a query to validate some condition, like the existence of a record (as opposed to entityload). I usually use ORM objects to persist to the DB. So, it’s pretty common for a service function to call both - which seems to be a problem in Lucee? Or maybe it should be a problem in ACF and isn’t - regardless, it’s a fairly customary practice in some apps I’ve worked on.

Is this really that unusual? If not, how are people handling it? Starting separate threads feels like overkill, especially having to handle them asynchronously.

Or do people really not do both?

On Apr 26, 2016, at 10:03 AM, Puritan Paul <@Puritan_Paul> wrote:

I’ve got zero threading experience, so it’s time to do some reading. Thanks for the suggestions.

On Apr 26, 2016, at 4:41 AM, Jon Clausen <@Jon_Clausen> wrote:

Hi Paul,

I meant start a separate thread for your logging using cfthread. Something like:

public any function logAuthenticationRequest(
required string username,
required string password,
required string deviceId,
required boolean status,
required string message
)
{

var threadName = "logAuthenticationRequest_" & createUUID();
       
thread name="#threadName#" action="run"
    object=object
    arguments=arguments
{
    var req = object.getNew('AuthenticationRequest');
   
    arguments.createdDate = datetime.getNow();

    if ( req.populate( context = arguments ).validate() )
        req.save();
   
}
   
return cfthread[ threadName ];

}

Debugging thread errors is a bit more involved, but logging is an example of when they can come in really handy.

On April 25, 2016 at 9:22:35 PM, Puritan Paul (@Puritan_Paul) wrote:

On Apr 25, 2016, at 5:18 PM, Jon Clausen <@Jon_Clausen> wrote:

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:

Yep, I figured that might be the case. Wouldn’t surprise me at all if I were approaching incorrectly. Just hoping to figure out what I’m doing incorrectly, if that’s the case.

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?

Mostly because I’m not sure what that means :slight_smile: Do you mean put a transaction inside the logging function itself as opposed to wrap the entire thing in a transaction?

Jon


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.571f53d0.713bc17a.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/53ACAAD2-78B0-46CA-9D0F-093ADFA0A0A0%40gmail.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.571fde25.84bd528.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/E613C216-7309-4AD1-ACC7-61A5B97FCC18%40gmail.com.
For more options, visit https://groups.google.com/d/optout.

It looks like it’s something related to Taffy, for sure. Without posting a sample of that, it’d be hard to debug.On April 26, 2016 at 6:36:22 PM, Puritan Paul (@Puritan_Paul) wrote:

Right, this makes sense. Sounds like I’ve just gotten away with some laziness up to now.

I removed the outer transaction call and pushed it into the service function like so:

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 );
    } else {

        transaction {
            try {
                var user = object.get( name = 'User', id = authenticate.UserId );
                user
                    .updateAuthenticationToken( deviceId = arguments.deviceId )
                    .save();

                status.success().setDetails( {token: user.getAuthenticationTokenByDevice( deviceId = arguments.deviceId )} );
                transaction action="commit";            
            }
            catch( any e ) {
                transaction action="rollback";
                rethrow;
            }
        }
        
    }

    logAuthenticationRequest( 
        username = arguments.username, 
        password = arguments.password, 
        deviceId = arguments.deviceId, 
        status = status.isValid(), 
        message = error );

    return status;
}

And now I’m getting some kind of StackOverflow error. But maybe it’s a Taffy issue? I can’t really tell. Thanks a lot for all your help.

An unhandled exception occurred: java.lang.StackOverflowError –
ERROR WHEN LOGGING EXCEPTION
Catch

additional Struct

Detail  
    string  
ErrNumber  
    number 0  
ErrorCode  
    string 0  
Extended_Info  
    string  
ExtendedInfo  
    string  
Message  
    string Element at position [1] doesn't exist in array  
StackTrace  
    string Element at position [1] doesn't exist in array
    at lucee.runtime.type.ArrayImpl.invalidPosition(ArrayImpl.java:194):194
    at lucee.runtime.type.ArrayImpl.getE(ArrayImpl.java:171):171
    at lucee.runtime.type.ArrayImpl.get(ArrayImpl.java:124):124
    at lucee.runtime.type.util.ArraySupport.get(ArraySupport.java:314):314
    at lucee.runtime.util.VariableUtilImpl.get(VariableUtilImpl.java:255):255
    at lucee.runtime.util.VariableUtilImpl.getCollection(VariableUtilImpl.java:249):249
    at lucee.runtime.PageContextImpl.getCollection(PageContextImpl.java:1416):1416
    at core.api_cfc$cf.udfCall1(/Users/jonathanprice/Websites/Taffy/atuttle-Taffy-75b0912/core/api.cfc:163):163
    at core.api_cfc$cf.udfCall(/Users/jonathanprice/Websites/Taffy/atuttle-Taffy-75b0912/core/api.cfc):-1
    at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:111):111
    at lucee.runtime.type.UDFImpl._call(UDFImpl.java:328):328
    at lucee.runtime.type.UDFImpl.call(UDFImpl.java:229):229
    at lucee.runtime.ComponentImpl._call(ComponentImpl.java:642):642
    at lucee.runtime.ComponentImpl._call(ComponentImpl.java:524):524
    at lucee.runtime.ComponentImpl.call(ComponentImpl.java:1761):1761
    at lucee.runtime.listener.ModernAppListener.call(ModernAppListener.java:405):405
    at lucee.runtime.listener.ModernAppListener.onError(ModernAppListener.java:392):392
    at lucee.runtime.PageContextImpl.execute(PageContextImpl.java:2273):2273
    at lucee.runtime.PageContextImpl.execute(PageContextImpl.java:2225):2225
    at lucee.runtime.engine.CFMLEngineImpl.serviceCFML(CFMLEngineImpl.java:456):456
    at lucee.loader.servlet.CFMLServlet.service(CFMLServlet.java:47):47
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:725):725
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291):291
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206):206
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52):52
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239):239
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206):206
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219):219
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106):106
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501):501
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142):142
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79):79
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610):610
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88):88
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:537):537
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1085):1085
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:658):658
    at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:222):222
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1556):1556
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1513):1513
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142):1142
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617):617
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61):61
    at java.lang.Thread.run(Thread.java:745):745

TagContext Array

    1 Struct

        codePrintHTML  
            string 161:                             </cfif>

162: <cfif structKeyExists(root,“tagContext”)>
163: <cfset data.tagContext = root.tagContext[1].template & " [Line #root.tagContext[1].line#]" />
164:
165: <!— MAKE IT LOOK GOOD! —>

        codePrintPlain  
            string 161:                              

162:
163:
164:
165:

        column  
            number 0  
        id  
            string ??  
        line  
            number 163  
        Raw_Trace  
            string core.api_cfc$cf.udfCall1(/Users/jonathanprice/Websites/Taffy/atuttle-Taffy-75b0912/core/api.cfc:163)  
        template  
            string /Users/jonathanprice/Websites/Taffy/atuttle-Taffy-75b0912/core/api.cfc  
        type  
            string cfml  
type  
    string expression  

On Apr 26, 2016, at 2:31 PM, Jon Clausen <@Jon_Clausen> wrote:

Depends on if you are within a transaction when you perform that validation. The issue, from what I can see, is that you are running into is that you are within an open transaction block when you attempt to run those additional validation queries.

It’s really a processing flow issue and the solution is to perform your validation first before you enter the transactional state or to use ORM methods in your validation so that the ORM session state is consistent, along with the connection.

Ideally, you’ve ensured the record you are about to persist meets all of your validation requirements before you open that transaction up.

Jon

On April 26, 2016 at 3:23:30 PM, Puritan Paul (@Puritan_Paul) wrote:

Okay, so this is turning into a broader issue that I’m unclear about how to handle. I often use a query to validate some condition, like the existence of a record (as opposed to entityload). I usually use ORM objects to persist to the DB. So, it’s pretty common for a service function to call both - which seems to be a problem in Lucee? Or maybe it should be a problem in ACF and isn’t - regardless, it’s a fairly customary practice in some apps I’ve worked on.

Is this really that unusual? If not, how are people handling it? Starting separate threads feels like overkill, especially having to handle them asynchronously.

Or do people really not do both?

On Apr 26, 2016, at 10:03 AM, Puritan Paul <@Puritan_Paul> wrote:

I’ve got zero threading experience, so it’s time to do some reading. Thanks for the suggestions.

On Apr 26, 2016, at 4:41 AM, Jon Clausen <@Jon_Clausen> wrote:

Hi Paul,

I meant start a separate thread for your logging using cfthread. Something like:

public any function logAuthenticationRequest(
required string username,
required string password,
required string deviceId,
required boolean status,
required string message
)
{

var threadName = "logAuthenticationRequest_" & createUUID();
       
thread name="#threadName#" action="run"
    object=object
    arguments=arguments
{
    var req = object.getNew('AuthenticationRequest');
   
    arguments.createdDate = datetime.getNow();

    if ( req.populate( context = arguments ).validate() )
        req.save();
   
}
   
return cfthread[ threadName ];

}

Debugging thread errors is a bit more involved, but logging is an example of when they can come in really handy.

On April 25, 2016 at 9:22:35 PM, Puritan Paul (@Puritan_Paul) wrote:

On Apr 25, 2016, at 5:18 PM, Jon Clausen <@Jon_Clausen> wrote:

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:

Yep, I figured that might be the case. Wouldn’t surprise me at all if I were approaching incorrectly. Just hoping to figure out what I’m doing incorrectly, if that’s the case.

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?

Mostly because I’m not sure what that means :slight_smile: Do you mean put a transaction inside the logging function itself as opposed to wrap the entire thing in a transaction?

Jon


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.571f53d0.713bc17a.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/53ACAAD2-78B0-46CA-9D0F-093ADFA0A0A0%40gmail.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.571fde25.84bd528.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/E613C216-7309-4AD1-ACC7-61A5B97FCC18%40gmail.com.
For more options, visit https://groups.google.com/d/optout.