Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OGM-1430 Support scripting stored procedures for infinispan remote (#43) #1004

Closed

Conversation

ntviet18
Copy link
Contributor

Hi @fax4ever @Sanne @DavideD could you please review this pull request? It's basically the same as #1000. But for Infinitispan Remote module.

@@ -0,0 +1,7 @@
// mode=local,language=javascript,parameters=[id,title]
Copy link
Contributor

@fax4ever fax4ever Apr 13, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @ntviet18 . Nice work again.
Maybe we can add a different test, where the stored procedure works (read or write) with cache data. Thank you for contribution.

Copy link
Member

@DavideD DavideD Apr 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can add a different test, where the stored procedure works (read or write) with cache data.

I don't think this test needs to be too complicated. The purpose of this issue is for OGM to be able to call stored procedures on Infinispan. Once you call a stored procedure and you can read the value it returns, we don't really care where the value is coming from. We might want to add an additional test in the integration test module to check for storedprocedures returning values previously inserted in the cache, but it can wait and we can make it in a separate issue.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DavideD I created this Issue to validate a full Data integration scenario.

@ntviet18 ntviet18 force-pushed the OGM-1430-infinispan-remote-scripting branch from 5f11648 to ef474fb Compare April 16, 2018 09:14
@ntviet18
Copy link
Contributor Author

@fax4ever Thank you. Please see the updates.

@DavideD
Copy link
Member

DavideD commented Apr 16, 2018

We will integrate this pull request after #1006
Can you rebase this on top of it?

@ntviet18
Copy link
Contributor Author

@DavideD sure

@DavideD
Copy link
Member

DavideD commented Apr 16, 2018

Thanks

@ntviet18 ntviet18 force-pushed the OGM-1430-infinispan-remote-scripting branch from ef474fb to adfe2ab Compare April 16, 2018 10:35
@ntviet18 ntviet18 force-pushed the OGM-1430-infinispan-remote-scripting branch from adfe2ab to e4c7bb2 Compare April 16, 2018 12:03
@fax4ever
Copy link
Contributor

With the merge of OGM-1429 Infinispan embedded stored procedures need to rebase this PR on top of master. The four commits at bottom is already present on the master.

@ntviet18
Copy link
Contributor Author

@fax4ever, I rebased

@fax4ever
Copy link
Contributor

Thank you @ntviet18

@DavideD
Copy link
Member

DavideD commented Apr 16, 2018

We are preparing a release and I think we will merge in the next one, I've started to review it though

Copy link
Member

@DavideD DavideD left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice, but I sitll have some remarks.

Thanks a lot, we will include this in 5.4 Alpha2 probably

return tuple;
}
catch (Exception e) {
throw log.cannotExtractTuple( e );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message seems a bit vague. I think we might add some additional information if we raise the exception and the caller deal with it. After all this is a utility method. For example you could also add the name of the stored procedure that caused the exception.

}

/**
* Extract tuple values from given object.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An example in the javadoc would be very helpful

/**
* @author The Viet Nguyen &ntviet18@gmail.com&
*/
public class TupleHelper {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some javadoc explaining that the purpose of this class is to collect methods used to convert an object into a collection of tuples would be helpful. I wonder if TuplesExtractor would be a better name. Not sure. The method could become something like extractFromMap(...), extractFromObject(...) and so on

@SkipByGridDialect(
value = { INFINISPAN_REMOTE },
comment = "This dialects does not throw exception when using not registered parameters."
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, but it seems it should. What happens if the parameter is not registered?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean this test is supposed to work for all the dialects supporting stored procedures.
By the way, what JPA says about invalid parameters? Maybe we need a specific exception. I think we need to check.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We cannot determine the invalid parameter before sending it to the execution because it's optional for Infinispan. However, we can analyze the execution result and extract the parameter name. Should we implement it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I think we should do that. Unless, it's too complicated

/**
* @author The Viet Nguyen &ntviet18@gmail.com&
*/
public class TupleHelperTest {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mentioned this before, but some javadoc with an example would help a lot. Like this is the Object and this is the expected tuple.

}
catch (IntrospectionException | InvocationTargetException | IllegalAccessException e) {
throw log.cannotExtractStoredProcedureResultSet( storedProcedureName, obj, e );
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah ah! So it was already working like I expected initially, basically you replaced a clear error message with something vague. Please make sure to revert this change.

StoredProcedureQuery storedProcedureQuery = em.createStoredProcedureQuery( Car.SIMPLE_VALUE_PROC, Car.class );
storedProcedureQuery.registerStoredProcedureParameter( 0, Integer.class, ParameterMode.IN );
storedProcedureQuery.setParameter( 0, 1 );
storedProcedureQuery.getSingleResult();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In OgmJpaTestCase there is a method called inTransaction that you can use like this:

inTransaction( em -> {
    StoredProcedureQuery storedProcedureQuery = em.createStoredProcedureQuery( Car.SIMPLE_VALUE_PROC, Car.class );
    storedProcedureQuery.registerStoredProcedureParameter( 0, Integer.class, ParameterMode.IN ); 
    storedProcedureQuery.setParameter( 0, 1 );
    storedProcedureQuery.getSingleResult();
} );

We are trying to use it in all the new tests and this way you can remove the setup and tear down methods

RemoteCache<String, String> scriptCache = provider.getScriptCache();
scriptCache.put( Car.SIMPLE_VALUE_PROC, toResourceString( "/storedprocedures/simpleValueProcedure.js" ) );
scriptCache.put( Car.RESULT_SET_PROC, toResourceString( "/storedprocedures/resultSetProcedure.js" ) );
scriptCache.put( "exceptionalProcedure", toResourceString( "/storedprocedures/exceptionalProcedure.js" ) );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice

@@ -0,0 +1,2 @@
// mode=local,language=javascript
param;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a new line at the end of the file, please?

We couldn't find a way to add the check in checkstyle but it's the way we commit code

Copy link
Contributor

@fax4ever fax4ever left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @ntviet18. Could you the comments here? Thank you

@@ -0,0 +1,7 @@
// mode=local,language=javascript,parameters=[id,title]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DavideD I created this Issue to validate a full Data integration scenario.

@@ -158,4 +177,12 @@ public static InfinispanRemoteDatastoreProvider getProvider(SessionFactory sessi
}
return InfinispanRemoteDatastoreProvider.class.cast( provider );
}

private static String toResourceString(String path) {
return toString( InfinispanRemoteTestHelper.class.getResourceAsStream( path ) );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I miss something.. When the input stream comes closed? Thanks

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you, I added try-with-resource in method below

* @author The Viet Nguyen &amp;ntviet18@gmail.com&amp;
*/
@TestForIssue(jiraKey = { "OGM-1430" })
public class InfinispanNamedParametersStoredProcedureCallTest extends OgmJpaTestCase {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe @RunWith(InfinispanRemoteServerRunner.class) is missing

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have checked, but somehow the factory is not created. Did I miss something?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check you are using the right one, in this case it should be: @Runwith(InfinispanRemote**Jpa**ServerRunner.class)

@@ -109,7 +115,7 @@
@Override
public void start() {
hotrodClient = HotRodClientBuilder.builder().withConfiguration( config, marshaller ).build();
hotrodClient.start();
scriptManager = HotRodClientBuilder.builder().withConfiguration( config, new GenericJBossMarshaller() ).build();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can add a comment here. We need a second cache manager as workaround, as suggested here: https://issues.jboss.org/browse/ISPN-8020. When this issue will be closed, we could remove use hotrodClient.

@DavideD
Copy link
Member

DavideD commented Apr 16, 2018

By the way, we also need some documentation in the manual about the fact that we can now call stored procedures with Infinispan,

@ntviet18 ntviet18 force-pushed the OGM-1430-infinispan-remote-scripting branch 2 times, most recently from 0045144 to 48d66dc Compare April 16, 2018 15:46
@ntviet18
Copy link
Contributor Author

@DavideD @fax4ever, Thank you. I have resolved some of your comments. But could you please mark a section in the documentation where I can describe about the stored procedures?

@@ -59,7 +55,7 @@
Callable<?> callable = instantiate( storedProcedureName, className, classLoaderService );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

callable doesn't say much about he content of the variable, I assume this is the storedProcedure isn't it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems it is not something from this PR, so never mind


private static final Log log = LoggerFactory.make( MethodHandles.lookup() );

private static final Pattern REFERENCE_ERROR_REGEXP = Pattern.compile( ".*\"([a-zA-Z_$]+)\" is not defined in <eval>.*" );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain to me quickly what's a reference error?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. We get this kind of error when we try to access an undefined variable. In our case, it's when we try to use unregistered stored procedure parameter.

}
catch (Exception e) {
if ( e instanceof HotRodClientException ) {
Matcher matcher = REFERENCE_ERROR_REGEXP.matcher( e.getMessage() );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you check with a regexp, we should add a test case Infinispan REmote to make sure that the error message doesn't change in future releases.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that the test is present on core: NamedParametersStoredProcedureCallTest::testExceptionWhenUsingNotRegisteredParameter.

hotrodClient.start();
// TODO temporary create another cache manager to handle remote script registration and invocation due to incompatibility of ProtoStreamMarshaller.
// When https://issues.jboss.org/browse/ISPN-8020 is closed, we could remove it and reuse the common hotrodClient.
scriptManager = HotRodClientBuilder.builder().withConfiguration( config, new GenericJBossMarshaller() ).build();
config = null; //no longer needed
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you stopping the scriptManager at some point?
Also, how come we don't need to start the hotrodClient anymore?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe it start by default

@ntviet18 ntviet18 force-pushed the OGM-1430-infinispan-remote-scripting branch from 48d66dc to 697ba6f Compare April 20, 2018 08:19
@fax4ever
Copy link
Contributor

@DavideD I reviewed again the PR, if you're agree, we can merge them! Thank you again @ntviet18

@DavideD
Copy link
Member

DavideD commented May 4, 2018

There is a new one

@DavideD DavideD closed this May 4, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants