Using Guice's #SessionScoped with Netty - dependency-injection

How do I implement #SessionScoped in a Netty based TCP server? Creating Custom Scopes is documented in Guice manual, but it seems that the solution only works for thread based and not asynchronous IO servers.
Is it enough to create the Channel Pipeline between scope.enter() and scope.exit()?

Disclaimer : this answer is for Netty 3. I've not had the opportunity to try Netty 4 yet, so I don't know if what follows can be applied to the newer version.
Netty is asynchronous on the network side, but unless you explicity submit tasks to Executors, or change threads by any other means, the handling of ChannelEvents by the ChannelHandlers on a pipeline is synchronous and sequential. For instance, if you use Netty 3 and have an ExecutionHandler on the pipeline, the scope handler should be upstream of the ExecutionHandler; for Netty 4, see Trustin Lee's comment.
Thus, you can put a handler near the beginning of your pipeline that manages the session scope, for example:
public class ScopeHandler implements ChannelUpstreamHandler {
#Override
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) {
if (e instanceof WriteCompletionEvent || e instanceof ExceptionEvent)
ctx.sendUpstream(e);
Session session = ...; // get session, presumably using e.getChannel()
scope.enter();
try {
scope.seed(Key.get(Session.class), session);
ctx.sendUpstream(e);
}
finally {
scope.exit();
}
}
private SessionScope scope;
}
A couple of quick remarks:
You will want to filter some event types out, especially WriteCompletionEvent and ExceptionEvent which the framework will put at the downstream end of the pipeline during event processing and wil cause reentrancy issues if not excluded. In our application, we use this kind of handler but actually only consider UpstreamMessageEvents.
The try/finally construct is not actually necessary as Netty will catch any Throwables and fire an ExceptionEvent, but it feels more idiomatic this way.
HTH

Related

Amazon SWF queries

Over the last couple of years, I have done a fair amount of work on Amazon SWF, but the following points are still unclear to me and I am not able to find any straight forward answers on any forums yet.
These are pretty basic requirements I suppose, sure others might have come across too. Would be great if someone can clarify these.
Is there a simple way to return a workflow execution result (maybe just something as simple as boolean) back to workflow starter?
Is there a way to catch Activity timeout exception, so that we can do run customised actions in such scenarios?
Why doesn't WorkflowExecutionHistory contains Activities, why just Events?
Why there is no simple way of restarting a workflow from the point it failed?
I am considering to use SWF for more business processes at my workplace, but these limitations/doubts are holding me back!
FINAL WORKING SOLUTION
public class ReturnResultActivityImpl implements ReturnResultActivity {
SettableFuture future;
public ReturnResultActivityImpl() {
}
public ReturnResultActivityImpl(SettableFuture future) {
this.future = future;
}
public void returnResult(WorkflowResult workflowResult) {
System.out.print("Marking future as Completed");
future.set(workflowResult);
}
}
public class WorkflowResult {
public WorkflowResult(boolean s, String n) {
this.success = s;
this.note = n;
}
private boolean success;
private String note;
}
public class WorkflowStarter {
#Autowired
ReturnResultActivityClient returnResultActivityClient;
#Autowired
DummyWorkflowClientExternalFactory dummyWorkflowClientExternalFactory;
#Autowired
AmazonSimpleWorkflowClient swfClient;
String domain = "test-domain;
boolean isRegister = true;
int days = 7;
int terminationTimeoutSeconds = 5000;
int threadPollCount = 2;
int taskExecutorThreadCount = 4;
public String testWorkflow() throws Exception {
SettableFuture<WorkflowResult> workflowResultFuture = SettableFuture.create();
String taskListName = "testTaskList-" + RandomStringUtils.randomAlphabetic(8);
ReturnResultActivity activity = new ReturnResultActivityImpl(workflowResultFuture);
SpringActivityWorker activityWorker = buildReturnResultActivityWorker(taskListName, Arrays.asList(activity));
DummyWorkflowClientExternalFactory factory = new DummyWorkflowClientExternalFactoryImpl(swfClient, domain);
factory.getClient().doSomething(taskListName)
WorkflowResult result = workflowResultSettableFuture.get(20, TimeUnit.SECONDS);
return "Call result note - " + result.getNote();
}
public SpringActivityWorker buildReturnResultActivityWorker(String taskListName, List activityImplementations)
throws Exception {
return setupActivityWorker(swfClient, domain, taskListName, isRegister, days, activityImplementations,
terminationTimeoutSeconds, threadPollCount, taskExecutorThreadCount);
}
}
public class Workflow {
#Autowired
private DummyActivityClient dummyActivityClient;
#Autowired
private ReturnResultActivityClient returnResultActivityClient;
#Override
public void doSomething(final String resultActivityTaskListName) {
Promise<Void> activityPromise = dummyActivityClient.dummyActivity();
returnResult(resultActivityTaskListName, activityPromise);
}
#Asynchronous
private void returnResult(final String taskListname, Promise waitFor) {
ActivitySchedulingOptions schedulingOptions = new ActivitySchedulingOptions();
schedulingOptions.setTaskList(taskListname);
WorkflowResult result = new WorkflowResult(true,"All successful");
returnResultActivityClient.returnResult(result, schedulingOptions);
}
}
The standard pattern is to host a special activity in the workflow starter process that is used to deliver the result. Use a process specific task list to make sure that it is routed to a correct instance of the starter. Here are the steps to implement it:
Define an activity to receive the result. For example "returnResultActivity". Make this activity implementation to complete the Future passed to its constructor upon execution.
When the workflow is started it receives "resultActivityTaskList" as an input argument. At the end the workflow calls this activity with a workflow result. The activity is scheduled on the passed task list.
The workflow starter creates an ActivityWorker and an instance of a Future. Then it creates an instance of "returnResultActivity" with that future as a constructor parameter.
Then it registers the activity instance with the activity worker and configures it to poll on a randomly generated task list name. Then it calls "start workflow execution" passing the generated task list name as an input argument.
Then it wait on the Future to complete. The future.get() is going to return the workflow result.
Yes, if you are using the AWS Flow Framework a timeout exception is thrown when activity is timed out. If you are not using the Flow framework than you are making your life 100 times harder. BTW the workflow timeout is thrown into a parent workflow as a timeout exception as well. It is not possible to catch a workflow timeout exception from within the timing out instance itself. In this case it is recommended to not rely on workflow timeout, but just create a timer that would fire and notify workflow logic that some business event has timed out.
Because a single activity execution has multiple events associated to it. It should be pretty easy to write code that converts history to whatever representation of activities you like. Such code would just match the events that relate to each activities. Each event always has a reference to the related events, so it is easy to roll them up into higher level representation.
Unfortunately there is no easy answer to this one. Ideally SWF would support restarting workflow by copying its history up to the failure point. But it is not supported. I personally believe that workflow should be written in a way that it never fails but always deals with failures without failing. Obviously it doesn't work in case of failures due to unexpected conditions. In this case writing workflow in a way that it can be restarted from the beginning is the simplest approach.

Spring #Transactional and Neo4j OGM session.getTransaction()

What is the correlation between Spring org.springframework.transaction.annotation.Transactional annotation and Neo4j OGM org.neo4j.ogm.session.Session.getTransaction() method.
I'm trying to access the current transaction via session.getTransaction() inside of the method annotated with Spring #Transactional but always getting null.
I have added a following code inside of my Spring MVC RestController method:
Transaction tx = session.beginTransaction();
try {
for (int i = 0; i < 10; i++) {
initializeNode(node);
}
}
tx.commit();
} catch (Throwable th) {
logger.error("Error while inserting mock data", th);
th.printStackTrace();
} finally {
tx.close();
}
in case of the following method:
private void initializeNode(TestNode node) {
System.out.println(session.getTransaction());
}
it prints current tx - so far everything is okay.
But in case of the following method:
private void initializeNode(TestNode node) {
System.out.println(session.getTransaction());
User admin = userDao.findByUsername("admin");
}
first time it prints current tx and then null... transaction disappear before commit for a some reason..
this is findByUsername method:
#Service
#Transactional
public class UserDaoImpl implements UserDao {
#Override
#Transactional(readOnly = true)
public User findByUsername(String username) {
return userRepository.findByUsername(username);
}
...
}
Right after that on commit I'm getting a following exception:
org.neo4j.ogm.exception.TransactionManagerException: Transaction is not current for this thread
at org.neo4j.ogm.session.transaction.DefaultTransactionManager.commit(DefaultTransactionManager.java:100)
at org.neo4j.ogm.transaction.AbstractTransaction.commit(AbstractTransaction.java:83)
at org.neo4j.ogm.drivers.embedded.transaction.EmbeddedTransaction.commit(EmbeddedTransaction.java:77)
What am I doing wrong ? Why transaction disappears ?
There are several issues and themes going on in this question. I will try and break them down and hopefully at the end it will all make sense.
As of the latest release of Spring Data Neo4j (4.1.x) there is no correlation between Spring's #Transactional and the Neo4j OGM's Session.getTransaction() or Session.beginTransaction() when called directly.
In your first two code blocks you are completely managing your OGM session lifecycle directly. Spring is not involved at all at this point and as you say it executes as expected.
In your updated third code block you are now expecting the session that you have manually opened to work with your Spring managed DAO. What will happen here is depends on the Neo4j Driver you are using with SDN but essentially because your DAO has the #Transactional annotation, Spring will intercept the call and start a brand new transaction all on its own on top of the one you are manually managing. At this point, we can't make any guarantees about the behaviour but the easiest explanation would be to say that it will be unexpected (again, depending on the driver used).
So how can you fix this?
I'm going to assume you want to use Spring Transactions and Spring Data Neo4j. If that's the case you will want to start by:
Changing your DAO to use Spring Data Repositories. This gives you a lot of free persistence functionality like finders, saves, deletes etc.
Putting the #Transactional annotation around the unit of work you want to accomplish. You might have a method that calls userRepository.findByUserName(), modifies that user and calls userRepository.save(user). In a web environment this is typically some sort of service method.
Removing any code that manually starts or ends an OGM session transaction.
You can find a very short code sample here and a longer code sample here.
A more comprehensive guide can also be found here.
In Spring Data Neo4j 4.2.x we hope to introduce some more powerful and friendlier #Transactional behaviour so keep posted for that update.

Inject bridge-code in JavaFX WebView before page-load?

I want to load some content or page in a JavaFX WebView and offer a Bridge object to Java so the content of the page can do calls into java.
The basic concept of how to do this is described here: https://blogs.oracle.com/javafx/entry/communicating_between_javascript_and_javafx
Now my question is: When is a good time inject the bridge-object into the WebView so it is available as soon as possible.
One option would be after page load as described here: https://stackoverflow.com/a/17612361/1520422
But is there a way to inject this sooner (before the page content itself is initialized), so the bridge-object is available DURING page-load (and not only after page-load)?
Since no one has answered, I'll tell you how I'm doing it, although it is ugly. This provides the ability for the page to function normally in non-Java environments but receive a Java object in Java environments.
I start by providing an onStatusChanged handler to the WebEngine. It listens for a magic value for window.status. If the magic value is received, the handler installs the Java object. (In my case, it's more complex, because I have some more complex orchestration: I'm executing a script that provides a client-side API for the page and then sets another magic value on window.status to cause the Java object to be sent to an initialization method of the client-side API).
Then in my target page, I have the following code in the first script in the page:
window.status = "MY-MAGIC-VALUE";
window.status = "";
This code is essentially a no-op in a "normal" browser but triggers the initialization when running in the custom JavaFX embedding.
In Java 8, you can trigger event changing from SCHEDULED to RUNNING to inject objects at this time. The objects will present in WebEngine before JavaScript running. Java 7, I see the state machine quite differs in operating, no solution given for Java 7.
webEngine.getLoadWorker().stateProperty().addListener(
new ChangeListener<State>(){
public void changed(ObservableValue<? extends State> ov,
State oldState,
State newState)
{
// System.out.println("old: "+oldState+", new: "+newState);
if(newState == State.RUNNING &&
oldState == State.SCHEDULED){
JSObject window = (JSObject)webEngine.executeScript("window");
window.setMember("foutput", foutput);
}
}
});

EJB3: How to inject DataSource in EJB3 during Junit testing as raw POJO

Hi quick question about injecting an alternative data-source during integration testing of an (EJB 3.0) EJB through its raw POJO API using junit.
I have been converting raw POJO services to EJB3 session beans. To do so has really just meant annotating the POJOs directly. The services are also accompanied by existing junit integration tests (that check the result of methods that query a real test database).
Several of these services require a direct java.sql.Connection and so I intend to configure this through an injected DataSource. The intention of this is so that I can deploy the bean directly to an app server (WLS, as it happens). However, I also want the existing integration tests to continue to work. These tests run against their own test database so I need to be able to inject the test configuration when running the integration tests (in a POJO/ non-container environment).
The question is:
Once I've set up my EJB, is there no way that I can override the injected bean without operating inside a container?
Put another way, is there no straightforward way to inject a new JNDI configuration when running the raw POJO integration tests?
An example service resembles the following:
#Stateless(mappedName="MyInterface")
public class MyClassImpl implements MyInterface {
...
#Resource(name="jdbc/MyAppServerDataSourceJNDIName")
DataSource ds;
Connection conn;
...
}
N.B. I don't intend to leave the DataSource and Connection in the services, I just want to get something sensible working before organically refactoring it.
Solutions I'm considering:
One (pretty awful) notion I have is to just provide a setter on the Connection in the service that is package-private. This way, my junit tests can set the Connection prior to execution. Then, in an app-server environment, the injected DS will be used. Not pretty though.
I've taken a look at ejb3unit (BaseSessionBeanFixture) and am considering that.
I also understand that I could create an EJB container in the junit and run within the container. The thing is, I'd like to test the base functionality using straightforward junit tests and against the POJOs (not the EJBs).
I know this can be done in spring (I'm a bit of an EJB novice) and am considering wiring the EJBs using spring config.
There's a lot of info out there but nothing specific (mostly JPA). Some good pointers elsewhere on SO though.
Thanks in advance.
My recommendations:
Remove the conn field, and use ds.getConnection() (and conn.close()) consistently. In your unit testing environment, you can mock DataSource/Connection (or otherwise provide obtain and provide "real" objects that are connected to a test database).
Add a setter to the EJB class. In fact, you can annotate the method for injection so that your container and unit test environments are even closer. You state that adding a setter would be "pretty awful", but I'm not sure why; setters are very much in the spirit of dependency injection. I agree that adding the setter to the business interface makes no sense, but it seems fine to add one to the bean class.
Example of #2:
#Resource(name="jdbc/MyAppServerDataSourceJNDIName")
public void setDataSource(DataSource ds) {
this.ds = ds;
}
This is the skeleton of the additional boilerplate to provide an injectable Connection to your service (package-private only) so that the EJB is usable as an EJB in an app-container but also as a POJO for junit testing with locally configurable Connection. Note, there is additional boiler-plate and we rely on tests calling #closeConnection to manage it properly.
This solution harks back to the original question and bkail's response:
#Stateless(mappedName = "MyClass")
...
public class MyClass {
// DataSource as configured for app-server environment
#Resource(name="app-dataSource")
private DataSource appDataSource;
private Connection conn;
/**
* Injectable {#code Connection} for injection by unit tests.
*/
/*package-private*/ void setConnection(Connection conn) {
this.conn = conn;
}
/**
* Get {#code Connection}. Use injected Connection if supplied, otherwise
* obtain one from the datasource. Client is responsible for closing this
* through call to #closeConnection (only!).
*/
final Connection getConnection() {
if (this.conn != null) {
return this.conn;
} else {
//Needs exception handling
//
return getDataSource().getConnection)
}
}
/*package-private*/ final void closeConnection(Connection conn) {
if (conn != null && conn != this.conn) {
try{
conn.close();
} catch ... {}
}
}
/*
* Accessor for the {#code DataSource}.
* #return the DataSource
*/
private DataSource getDataSource() {
if (ds == null) {
...
ds = (DataSource) ctx.lookup(jndiName);
...
}
return ds;
}
...
}
public class TestMyClass {
private Connection conn = null;
#BeforeClass
public void setUpBeforeClass() throws Exception {
...
conn = DriverManager.getConnection(...);
}
#Test
public void testMyMethod {
MyClass mc = new MyClass();
mc.setConnection(conn); // Set our own connection
// do test stuff
...
}
...
}

How to I bind a Hibernate Session to a thread in Grails?

I'm writing a multi-threaded application in Grails and the additional threads need access to GORM/Hibernate. When they try to access GORM I get the error "org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here".
OK fair enough, can someone guide me on the best way to set the threads up to have access? The error message almost sounds like you just need to change some config options yet I sense, it is not so simple...
There is a bean in Grails applications called “persistenceInterceptor” that can be used for this.
See this example from the JMS plugin on how to use it:
http://github.com/gpc/grails-jms/blob/master/src/groovy/grails/plugin/jms/listener/adapter/PersistenceContextAwareListenerAdapter.groovy#L21
Here is the interface:
https://github.com/grails/grails-core/blob/master/grails-core/src/main/groovy/grails/persistence/support/PersistenceContextInterceptor.java
And Hibernate impl:
https://github.com/grails/grails-data-mapping/blob/master/grails-datastore-gorm-support/src/main/groovy/org/grails/orm/hibernate4/support/HibernatePersistenceContextInterceptor.java
You need to put any GORM calls in a withTransaction closure. An example taken from a discussion of multi threading at
https://fbflex.wordpress.com/2010/06/11/writing-batch-import-scripts-with-grails-gsql-and-gpars/
Single threaded
user = User.findByUsername( photo.username )
multi threaded
User.withTransaction{
user = User.findByUsername( photo.username )
}
withNewSession will also work. In my case, I have low priority updates where the last update can always "win". version: false is also important here in order to avoid the StaleObjectException:
Thread.start {
try {
Widget.withNewSession {
xxx()
log.info "Asynchronously did some updates."
}
} catch (Exception ex) {
log.error "Failed to asynchronously do something...", ex
}
}
Luke Daley gave the right answer. Unfortunately, the links have changed. Thus, I'll update his answer and provide a code example to make this answer self-contained.
There is a bean in Grails applications called persistenceInterceptor that can be used for initializing the persistence context / session for Hibernate. You can inject the bean into one of your controller / service classes and start a new thread, e.g. using the following code snippet.
class YourControllerOrService {
PersistenceContextInterceptor persistenceInterceptor
def someOperation() {
...
Runnable yourTask = { ->
try {
if (persistenceInterceptor) {
persistenceInterceptor.init()
}
// execute the hibernate operations here in a transaction,
// e.g. call a method annotated with #Transactional
...
} catch (Exception e) {
log.error('Your error message', e)
} finally {
if (persistenceInterceptor) {
persistenceInterceptor.flush()
persistenceInterceptor.destroy()
}
}
}
Thread workerThread = new Thread(yourTask)
workerThread.start()
...
}
}
You'll find an exemplary implementation in the Grails JMS plug-in on GitHub.
The PersistenceContextInterceptor interface can be found on GitHub, too.

Resources