I have multiple existing Stateful Session Beans. I want to use a new library/framework that instantiates objects (outside the container manager). This framework does not conceptually have 'sessions'. I'm trying to develop a proof of concept to route calling of beans in different session contexts based on a map of session identifiers to session contexts.
Below are 2 handlers that are instantiated by the library. The first handler creates new BoundSessionContexts and maps them to generated keys. The second handler is suppose to be passed the key and based on it propagate to the appropriate corresponding sessionContext, lookup the beans in that context, and call those beans.
public class Handler1 implements Handler1Interface{
//**1**
WeldManager weldManager = (WeldManager) CDI.current().getBeanManager();
BoundSessionContext boundSessionCtx;
//**2**
Map<String, Object> sessionMap = new HashMap<>();
public Handler1(){
}
//**3**
#Override
public long start(){
long sessionId = new Random().nextLong();
//**4**
boundSessionCtx = weldManager.instance().select(BoundSessionContext.class, BoundLiteral.INSTANCE).get();
//**5**
//boundSessionCtx.associate(sessionMap);
//Make certain the sessionId isn't already in use.
while(SessionMapper.get(sessionId)!=null){
sessionId = new Random().nextLong();
}
//**6**
SessionMapper.put(sessionId, boundSessionCtx);
return sessionId;
}
//**7**
#Override
public void stop(long sessionId){
SessionMapper.remove(sessionId);
}
}
public class Handler2 implements Handler1Interface{
//**8**
#Inject
EJB1 ejb1;
//**9**
#Inject
EJB2 ejb2;
BeanManager beanManager;
BoundSessionContext boundSessionCxt;
//**10**
Map<String, Object> sessionMap = new HashMap<>();
public Handler2(){
}
#Override
public Object process(long sessionId, Object input){
lookupEJBs(sessionId);
//**11**
ejb1.method();
Object result = ejb2.method();
return result;
}
//**12**
private void lookupEJBs(long sessionId) {
boundSessionCxt = SessionMapper.get(sessionId);
boundSessionCxt.associate(sessionMap);
boundSessionCxt.activate();
beanManager = CDI.current().getBeanManager();
//**13**
TypeLiteral<EJB1> typeLiteral = new TypeLiteral<EJB1>() {};
Set<Bean<?>> beans = beanManager.getBeans(typeLiteral.getType());
Bean<?> bean = beanManager.resolve(beans);
ejb1 = bean.create(boundSessionCxt);
//**14**
TypeLiteral<EJB2> typeLiteral2 = new TypeLiteral<EJB2>() {};
beans = beanManager.getBeans(typeLiteral2.getType());
bean = beanManager.resolve(beans);
ejb2 = bean.create(boundSessionCxt);
}
I've never been able to call ejb2.method(). While I have used EJBs for many years this is my first attempt at manipulating contexts. I am definitively feeling lost. It's one thing to use the magic, it's another to warp that magic to your whim.
Questions (In no particular order):
A) Is what I'm trying to do 'reasonably' acheivable? Or is this a pipe dream? NOTE: I am currently using WELD-API 3.0.SP4, but I am not married to it.
B) I have never truly understood the reason for the map(10) that is associated with a context(12).
B1) What is it's purpose?
B2) How does it's use affect what I'm trying to do here?
B3) Am I correct in that I would want to associate and activate the context inside the object where I want to use the context beans?
C) Am I correct that #Inject (8 and 9) is pointless as the handler2 object is not instantiated/Injected by the bean manager.
Many thanks to anyone who can help me understand EJB/CDI session contexts better. :)
Related
When using spring-data-rest there is a post processing of Resource classes returned from Controllers (e.g. RepositoryRestControllers). The proper ResourceProcessor is called in the post processing.
The class responsible for this is ResourceProcessorHandlerMethodReturnValueHandler which is part of spring-hateoas.
I now have a project that only uses spring-hateoas and I wonder how to configure ResourceProcessorHandlerMethodReturnValueHandler in such a scenario. It looks like the auto configuration part of it still resides in spring-data-rest.
Any hints on how to enable ResourceProcessorHandlerMethodReturnValueHandler in a spring-hateoas context?
I've been looking at this recently too, and documentation on how to achieve this is non-existent. If you create a bean of type ResourceProcessorInvokingHandlerAdapter, you seem to lose the the auto-configured RequestMappingHandlerAdapter and all its features. As such, I wanted to avoid using this bean or losing the WebMvcAutoConfiguration, since all I really wanted was the ResourceProcessorHandlerMethodReturnValueHandler.
You can't just add a ResourceProcessorHandlerMethodReturnValueHandler via WebMvcConfigurer.addReturnValueHandlers, because what we need to do is actually override the entire list, as is what happens in ResourceProcessorInvokingHandlerAdapter.afterPropertiesSet:
#Override
public void afterPropertiesSet() {
super.afterPropertiesSet();
// Retrieve actual handlers to use as delegate
HandlerMethodReturnValueHandlerComposite oldHandlers = getReturnValueHandlersComposite();
// Set up ResourceProcessingHandlerMethodResolver to delegate to originally configured ones
List<HandlerMethodReturnValueHandler> newHandlers = new ArrayList<HandlerMethodReturnValueHandler>();
newHandlers.add(new ResourceProcessorHandlerMethodReturnValueHandler(oldHandlers, invoker));
// Configure the new handler to be used
this.setReturnValueHandlers(newHandlers);
}
So, without a better solution available, I added a BeanPostProcessor to handle setting the List of handlers on an existing RequestMappingHandlerAdapter:
#Component
#RequiredArgsConstructor
#ConditionalOnBean(ResourceProcessor.class)
public class ResourceProcessorHandlerMethodReturnValueHandlerConfigurer implements BeanPostProcessor {
private final Collection<ResourceProcessor<?>> resourceProcessors;
#Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
if (bean instanceof RequestMappingHandlerAdapter) {
RequestMappingHandlerAdapter requestMappingHandlerAdapter = (RequestMappingHandlerAdapter) bean;
List<HandlerMethodReturnValueHandler> handlers =
requestMappingHandlerAdapter.getReturnValueHandlers();
HandlerMethodReturnValueHandlerComposite delegate =
handlers instanceof HandlerMethodReturnValueHandlerComposite ?
(HandlerMethodReturnValueHandlerComposite) handlers :
new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
requestMappingHandlerAdapter.setReturnValueHandlers(Arrays.asList(
new ResourceProcessorHandlerMethodReturnValueHandler(delegate,
new ResourceProcessorInvoker(resourceProcessors))));
return requestMappingHandlerAdapter;
}
else return bean;
}
}
This has seemed to work so far...
I have a private list and I don't want that it can be modified from outside in general. Just adding from outside is allowed and only if the object is valid. Therefore I used to write it like this:
private List<Object> list = new ArrayList<>();
public List<Object> getList()
{
return Collections.unmodifiableList(list);
}
public void addObject(Object object)
{
if (isObjectValid(object)) //any validation
list.add(object);
}
Now for JavaFX purposes I turn the list to a property:
private ListProperty<Object> list =
new SimpleListProperty<>(FXCollections.observableArrayList());
To profit from the benefits of an property like data binding and the ListChangeListener I have to provide the property to the outer world. But then access to all methods of a list is provided, too. (To use a ReadOnlyListProperty has no effect since the list instance itself will never change.) What can I do to achieve all goals:
private ListProperty
ListChangeListener can be added from outside
Usable for binding dependencies from outside (the create methods form class Bindings)
No modifying of the property or list instance itself
Modifying of list content from outside only through my own methods
Not tested, but try:
private ListProperty<Object> list = new SimpleListProperty<>(FXCollections.observableArrayList());
private ReadOnlyListWrapper<Object> publicList = new ReadOnlyListWrapper<>();
and in the constructor:
publicList.bind(Bindings.createObjectBinding(
() -> FXCollections.unmodifiableObservableList(list.getValue()),
list));
then your accessor method is
public ReadOnlyListProperty<Object> getList() {
return publicList.getReadOnlyProperty();
}
Currently, I am using a Dictionary and Context.User.Identity.Name (code condensed for brevity):
[Authorize]
public class ServiceHub : Hub
{
static private Dictionary<string, HubUserProcess> UserProcesses = new Dictionary<string, HubUserProcess>();
public override Task OnConnected()
{
UserProcesses[Context.User.Identity.Name] = new HubUserProcess();
return base.OnConnected();
}
public override Task OnDisconnected()
{
// ... Remove from dictionary if key exists (not shown) ...
return base.OnConnected();
}
// Then I use UserProcesses[Context.User.Identity.Name] in all functions
}
In my HubUserProcess class, I have a bunch of web services that initialize in the constructor using the Context.User.Identity.Name. A coworker said that my approach is unsafe, so my biggest worry is one user accessing another user's private data (these variables can hold very sensitive information). What is the correct/safe way to store client variables?
My app has a ProviderFactory static class that has static utility methods passing back static instances of things like a logger. The rest of my app then can just grab a/the reference to the logger from anywhere without having to pass in the logger (common design practice).
So, another part of my app, the DbCacheProvider, has methods that make calls to the logger so internally it gets a reference to the logger from the factory and then issues calls to it.
My question is that using Moq, I want to verify methods on the logger are being called by the methods within the DbCacheProvider. I can do this using dependency injection when I pass a mock logger into the DbCacheProvider as a parameter, but I'm not passing the logger in (not do I want to). So, how would I verify the DbCacheProvider is making calls to the logger?
If you don't want to pass the logger in through the constructor you'd need to change your ProviderFactory while running unit tests to return your mocked logger.
Anyway there are a couple of reasons it's often suggested to set up dependency injection:
Your tests are more straightforward and don't involve finagling with custom factories
IoC frameworks like Unity, Ninject and Autofac make it easy to create objects when their dependencies are set up this way. If you set up all of your objects this way, the framework will do all the heavy lifting of creating the right objects and passing them in for you. The dependency injection is done automatically and won't be a burden for you.
Old question without an answer, I had a similar problem and solved it like this:
I have the following sample code and need to verify that not only was a method called but was called with a specific value.
public interface ILog
{
void Info(string message);
}
public interface ILogFactory
{
ILog GetLogger();
}
This is the class being tested, where the interface items are being injected:
public class NewAction
{
readonly ILogFactory _logger;
public NewAction(ILogFactory logger)
{
_logger = logger;
}
public void Step1()
{
_logger.GetLogger().Info("Step 1");
}
public void Step2()
{
_logger.GetLogger().Info("Step 2");
}
}
This is obviously a very simplistic view of my actual code, but I needed to verify that Step1 and Step2 are behaving as expected and passed the correct values to the Log, this would mean I also needed to ensure they occurred in the right order. My test:
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
// Arrange
var log = new Mock<ILog>();
var factory = new Mock<ILogFactory>();
factory.Setup(l => l.GetLogger()).Returns(log.Object);
// Act
var action = new NewAction(factory.Object);
action.Step1();
action.Step2();
// Assert
factory.Verify(l => l.GetLogger());
log.Verify(l => l.Info(It.Is<string>(s => s == "Step 1")));
log.Verify(l => l.Info(It.Is<string>(s => s == "Step 2")));
}
}
Hope this helps.
Basically I'm trying to create a SessionManager class which I can use to manage sessions in my MVC applications. For that I'm thinking the best way of doing so is by creating a wrapper class for HttpContext which would then allow me to access HttpContext.Current.Session.
To be honest, I'm not really sure about the whole thing, I just feel it's the logical way of doing so. I also want to create an ISessionManager and ISession interfaces, and then implement them according to my application's needs. For my current project, and for now, I need a InProc session management, but I might need to store session data in MSSQL Server when we decide to expand and use a web farm or a garden. That's why I'm trying to build a sort of an extensible framework right from the start.
Final note, I will be using Microsoft Unity to inject the concrete SessionManager of choice. I believe that's a good way to maintain a certain level of abstraction.
Any suggestions for achieving all that?
Thanks in advance! :)
Ok here's what I came up with, but I'm not sure that's the right way of doing this so your opinions are most welcome!
ISessionManager:
public interface ISessionManager
{
void RegisterSession(string key, object obj);
void FreeSession(string key);
}
SessionManager:
public class SessionManager : ISessionManager
{
private IDictionary<string, object> sessionDictionary;
public SessionManager(IDictionary<string, object> _sessionDictionary)
{
sessionDictionary = _sessionDictionary;
}
public IDictionary<string, object> Session
{
get
{
return sessionDictionary;
}
}
public void RegisterSession(string key, object obj)
{
sessionDictionary[key] = obj;
}
public void FreeSession(string key)
{
sessionDictionary[key] = null;
}
}
Then when I want to instantiate the class (inside my web app), I would do something like that:
var sessionManager = new SessionManager(HttpContext.Current.Session);
sessionManager.RegisterSession["myKey"] = someObject;
But I would prefer to avoid using magic strings as the key. I could include a constant string property like sessionKey = "myKey" in the class, but that would mean I could only store one object in the session manager, right?
Feedback please. :)