I am getting a strange error where the session I get from the request is sometimes null. Code looks like this:
#Stateless
#Path("/login")
public class GetLogin {
#Context
private HttpServletRequest httpRequest;
#POST
#Produces(MediaType.APPLICATION_JSON)
public Response login(){
final HttpSession session = httpRequest.getSession(true);
sessionId = session.getId();//Sometimes gives nullpointer Exceptions
.....//Rest works fine if that step holds
When I call to get the session id I sometimes get a nullpointer exception. Why is that? Is there anything I can do to stop that? I can repeat the exact same call over and over and it randomly creates nullpointer exceptions due to that while other times it works just fine. I have tried doing this all sort of ways, with methods waiting for it to get ready and so on. What I learned was that if it don't get ready instantly it will never get ready.
The get cookies method on the request do occasionally fail as well bit that is easy to work around by just taking the cookies as arguments in the function. Also it seems like I can get around this by telling the frontend to repeat the call if the first one failed, the second call always succeeds then for some reason. But that feels like a dirty solution, so I really want to fix this...
Any ideas?
Edit: Apparently if I let it fail it fails every other time, but if I handle it so that the servlet don't crash it fails 4 times in a row and then succeeds once. I tried doing this on a fresh install, I took the standard netbeans example rest webapp and just added the HttpRequest to it and then printed out the session id. If anyone got this to work please show me how...
Related
I have an spring boot (1.5.2.RELEASE) app that is using binary websocket (i.e. NO Stomp, AMQP pure binary buffer). In my test I am able to send messages back and forth which works just great.
However I am experiencing the following unexplained behaviour related to TestSecurityContexHolder during the websocket calls to the application.
The TestSecurityContextHolder has a context that is begin set correctly i.e. my customer #WithMockCustomUser is setting it and I can validate that when putting a breankpoint in the beginning of the test. I.e.
public class WithMockCustomUserSecurityContextFactory implements WithSecurityContextFactory<WithMockCustomUser>,
That works great and I am able to test server side methods that implement method level security such as
#PreAuthorize("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')")
public UserInterface get(String userName) {
…
}
The problem I have starting experiencing is when I want to do a full integration test of the app i.e. within the test i crate my own WebSocket connection to the app, using only java specific annotations i.e. (no spring annotaions in the client).
ClientWebsocketEndpoint clientWebsocketEndpoint = new ClientWebsocketEndpoint(uri);
.
#ClientEndpoint
public class ClientWebsocketEndpoint {
private javax.websocket.Session session = null;
private ClientBinaryMessageHandler binaryMessageHandler;
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
public ClientWebsocketEndpoint(URI endpointURI) {
try {
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
container.connectToServer(this, endpointURI);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
….
}
If try calling the websocket then I first see that the “SecurityContextPersistenceFilter” is removing the current SecurityContex which is fully expected. I actually want it to get remove since I want to test authentication anyway, since authentication is part of the websocket communication and not part of the http call in my case, but what bothers me is the following.
So far we had only one HTTP call (wireshark proves that) and the SecurityContextPersistenceFilter has cleared the session only once and by setting a breakpoint on the clear method i see that indeed it has been called only once. After 6 binary messaged (i.e. the SecurityContext is set in the 5 message received from the client) are being exchanged between the client and the server I do authentication with a custom token and write that token to the TestSecurityContextHolder btw SecurityContexHolder i.e.
SecurityContext realContext = SecurityContextHolder.getContext();
SecurityContext testContext = TestSecurityContextHolder.getContext();
token.setAuthenticated(true);
realContext.setAuthentication(token);
testContext.setAuthentication(token);
I see that the hashCode of that token is the same in bought ContexHolders which means that this is the same object. However next time I received a ByteBuffer from the client, the result of SecuriyContextHolder.getAuthentication() is null. I first though that his is related to the SecurityContextChannelInterceptor since i read a good article about websockets and spring i.e. here but this does not seems to be the case. The securityContextChannelInterceptor is not executed or called anywhere at least when putting breakpoints i see that IDE is not stopping there. Please note that I am deliberately not extending the AbstractWebSocketMessageBrokerConfigurer here since i do not need it i.e. this is plain simple binary websocket with no (STOMP AMQP etc. i.e. no known messaging ). However i see another class i.e. WithSecurityContextTestExecutionListener clearing the context
TestSecurityContextHolder.clearContext() line: 67
WithSecurityContextTestExecutionListener.afterTestMethod(TestContext) line: 143
TestContextManager.afterTestMethod(Object, Method, Throwable) line: 319
RunAfterTestMethodCallbacks.evaluate() line: 94
but only when the test finished!!! i.e. that is way after the SecurityContext is null, although manually set with customer token before. It seems that something like a filter (but for websockets i.e. not HTTP) is clearing the securityContext on each WsFrame received. I have no idea what that is. Also what might be also relative is: on the server side when i see the stack trace i can observe that StandardWebSocketHandlerAdapter is being called which is creating the StandardWebSocketSession.
StandardWebSocketHandlerAdapter$4.onMessage(Object) line: 84
WsFrameServer(WsFrameBase).sendMessageBinary(ByteBuffer, boolean) line: 592
In the StandardWebSocketSession i see that there is a field "Principal user". Well who is supposed to set that principal i.e. i do not see any set methods there the only way to set it is is during the "AbstractStandardUpgradeStrategy" i.e. in the first call but then what to do once the session it established? i.e. the rfc6455 defined the
10.5. WebSocket Client Authentication
This protocol doesn't prescribe any particular way that servers can
authenticate clients during the WebSocket handshake. The WebSocket
server can use any client authentication mechanism available
for me that means that i SHOULD be able to define the user Principal in the later stage whenever i want.
here is how to test is runned
#RunWith(SpringRunner.class)
#TestExecutionListeners(listeners={ // ServletTestExecutionListener.class,
DependencyInjectionTestExecutionListener.class,
TransactionalTestExecutionListener.class,
WithSecurityContextTestExecutionListener.class
}
)
#SpringBootTest(classes = {
SecurityWebApplicationInitializerDevelopment.class,
SecurityConfigDevelopment.class,
TomcatEmbededDevelopmentProfile.class,
Internationalization.class,
MVCConfigDevelopment.class,
PersistenceConfigDevelopment.class
} )
#WebAppConfiguration
#ActiveProfiles(SConfigurationProfiles.DEVELOPMENT_PROFILE)
#ComponentScan({
"org.Server.*",
"org.Server.config.*",
"org.Server.config.persistence.*",
"org.Server.core.*",
"org.Server.logic.**",
})
#WithMockCustomUser
public class workingWebSocketButNonWorkingAuthentication {
....
here is the before part
#Before
public void setup() {
System.out.println("Starting Setup");
mvc = MockMvcBuilders
.webAppContextSetup(webApplicationContext)
.apply(springSecurity())
.build();
mockHttpSession = new MockHttpSession(webApplicationContext.getServletContext(), UUID.randomUUID().toString());
}
And in order to summarize my question is what could be causing the behaviour where Security Context returned from the bought TestSecurityContextHolder or SecurityContextHolder is null after another ByteBuffer (WsFrame) is being received from the client?.
#Added 31 May:
I found by coincidence when running the test mulitple times that sometimes the contex is not null and the test OK i.e. sometimes the contex is indeed filled with the token i supplied. I guess this has something to do with the fact that the Spring Security Authentication is bound to a ThreadLocal, will need further digging.
#Added 6 June 2017:
I can confirm know that the problem is in the threads i.e.the authentication is successful but when jumping between http-nio-8081-exec-4 to nio-8081-exec-5 the Security Contex is beeing lost and that is in the case where i have set the SecurityContextHolder Strategy to MODE_INHERITABLETHREADLOCAL. Any sugesstions are greatly appreciated.
Added 07 June 2017
If i add the SecurityContextPropagationChannelInterceptor does not propagate the security Context in case of the simple websocket.
#Bean
#GlobalChannelInterceptor(patterns = {"*"})
public ChannelInterceptor securityContextPropagationInterceptor()
{
return new SecurityContextPropagationChannelInterceptor();
}
Added 12 June 2017
did the test with the Async notation i.e. the one found here. spring-security-async-principal-propagation . That is showing that the Security Context is being transferred correctly between methods that are executed in different threads within spring, but for some reason the same thing does not work for Tomcat threads i.e http-nio-8081-exec-4 , http-nio-8081-exec-5 , http-nio-8081-exec-6 , http-nio-8081-exec-7 etc. I have the feeling that his has something to do with the executor but so far i do not know how to change that.
Added 13 June 2017
I have found by printing the current threads and the Security Contex that the very first thread i.e. http-nio-8081-exec-1 does have the security context populated as expected i.e. per mode MODE_INHERITABLETHREADLOCAL, however all further threads i.e http-nio-8081-exec-2, http-nio-8081-exec-3 do not. Now the question is: Is that expected? I have found here working with threads in Spring the statement that
you cannot share security context among sibling threads (e.g. in a thread pool). This method only works for child threads that are spawned by a thread that already contains a populated SecurityContext.
which basically explains it, however since in Java there is no way to find out the parent of the thread , I guess the question is who is creating the Thread http-nio-8081-exec-2 , is that the dispatcher servlet or is that tomcat somehow magically deciding now i will create a new thread. I am asking that because i see that sometimes parts of the code are executed in the same thread or in different depending on the run.
Added 14 June 2017
Since i do not want to put all in one i have created a separated question that deals with the problem of finding the answer how to propagate the security context to all sibling threads created by the tomcat in case of a spring boot app. found here
I'm not 100% sure I understand the problem, but it's unlikely that the Java dispatcher servlet will create a new thread without being told to. I think tomcat handles each request in a different thread, so that might be why the threads are being created. You can check this
and this out. Best of luck!
I recently ran into an instance where I wanted to hit the database from a Task I have running periodically within a web application. I refactored the code to use the ThreadStaticSessionContext so that I could get a session without an HttpContext. This works fine for reads, but when I try to flush an update from the Task, I get the "Index was out of range. Must be non-negative and less than the size of the collection." error. Normally what I see for this error has to do with using a column name twice in the mapping, but that doesn't seem to be the issue here, as I'm able to update that table if the session is associated with a request (and I looked and I'm not seeing any duplicates). It's only when the Task tries to flush that I get the exception.
Does anyone know why it would work fine from a request, but not from a call from a Task?
Could it be because the Task is asynchronous?
Call Stack:
at System.ThrowHelper.ThrowArgumentOutOfRangeException()
at System.Collections.Generic.List`1.System.Collections.IList.get_Item(Int32 index)
at NHibernate.Engine.ActionQueue.ExecuteActions(IList list)
at NHibernate.Engine.ActionQueue.ExecuteActions()
at NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource session)
at NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event)
at NHibernate.Impl.SessionImpl.Flush()
Session Generation:
internal static ISession CurrentSession {
get {
if(HasSession) return Initializer.SessionFactory.GetCurrentSession();
ISession session = Initializer.SessionFactory.OpenSession();
session.BeginTransaction();
CurrentSessionContext.Bind(session);
return session;
}
}
private static bool HasSession {
get { return CurrentSessionContext.HasBind(Initializer.SessionFactory); }
}
Task that I want to access the database from:
_maid = Task.Factory.StartNew(async () => {
while(true) {
if(CleaningSession != null) CleaningSession(Instance, new CleaningSessionEventArgs { Session = UnitOfWorkProvider.CurrentSession });
UnitOfWorkProvider.TransactionManager.Commit();
await Task.Delay(AppSettings.TempPollingInterval, _paycheck.Token);
}
//I know this function never returns, I'm using the cancellation token for that
// ReSharper disable once FunctionNeverReturns
}, _paycheck.Token);
_maid.GetAwaiter().OnCompleted(() => _maid.Dispose());
Edit: Quick clarification about some of the types above. CleaningSession is an event that is fired to run the various things that need to be done, and _paycheck is the CancellationTokenSource for the Task.
Edit 2: Oh yeah, and this is using NHibernate version 4.0.0.4000
Edit 3: I have since attempted this using a Timer, with the same results.
Edit 4: From what I can see of the source, it's doing a foreach loop on an IList. Questions pertaining to an IndexOutOfRangeException in a foreach loop tend to suggest a concurrency issue. I still don't see how that would be an issue, unless I misunderstand the purpose of ThreadStaticSessionContext.
Edit 5: I thought it might be because of requests bouncing around between threads, so I tried creating a new SessionContext that combines the logic of the WebSessionContext and ThreadStaticSessionContext. Still getting the issue, though...
Edit 6: It seems this has something to do with a listener I have set up to update some audit fields on entities just before they're saved. If I don't run it, the commit occurs properly. Would it be better to do this through an event than OnPreInsert, or use an interceptor instead?
After muddling through, I found out exactly where the problem was. Basically, there was a query that was run to load the current user record called from inside of the PreUpdate event in my listener.
I came across two solutions to this. I could cache the user in memory, avoiding the query, but having possibly stale data (not that anything other than the id matters here). Alternatively, I could open a temporary stateless session and use that to look up the user in question.
I'm trying to use Laravel IoC by creating a singleton object. I'm following the pattern from tutorial as below. I have put a Log message into object (Foobar in this example) constructor and I can see that object is being created every time I refresh page in browser. How is the singleton pattern meant for Laravels IoC? I understood that its shared object for entire application but its obviously being created every time its requested by App:make(...) Can someone explain please. I thought I would use the singleton pattern for maintaining shared MongoDB connection.
App::singleton('foo', function()
{
return new FooBar;
});
What has been said in Laravel Doc
Sometimes, you may wish to bind something into the container that
should only be resolved once, and the same instance should be returned
on subsequent calls into the container:
This is how you can bind a singleton object and you did it right
App::singleton('foo', function()
{
return new FooBar;
});
But, the problem is, you are thinking about the whole process of the request and response in the wrong way. You mentioned that,
I can see that object is being created every time I refresh page in
browser.
Well, this is normal behaviour of HTTP request because every time you are refreshing the page means every time you are sending a new request and every time the application is booting up and processing the request you've sent and finally, once the application sends the response in your browser, it's job is finished, nothing is kept (session, cookie are persistent and different in this case) in the server.
Now, it has been said that the same instance should be returned on subsequent calls, in this case, the subsequent calls mean that, if you call App::make(...) several times on the same request, in the single life cycle of the application then it won't make new instances every time. For example, if you call twice, something like this
App::before(function($request)
{
App::singleton('myApp', function(){ ... });
});
In the same request, in your controller, you call at first
class HomeController {
public function showWelcome()
{
App::make('myApp'); // new instance will be returned
// ...
}
}
And again you call it in after filter second time
App::after(function($request, $response)
{
App::make('myApp'); // Application will check for an instance and if found, it'll be returned
});
In this case, both calls happened in the same request and because of being a singleton, the container makes only one instance at the first call and keeps the instance to use it later and returns the same instance on subsequent calls.
It is meant to be used multiple times throughout the applications instance. Each time you refresh the page, it's a new instance of the application.
Check this out for more info and practical usage: http://codehappy.daylerees.com/ioc-container
It's written for L3, but the same applies for L4.
I'm using the TransactionScope class within a project based on Silverlight and RIA services. Each time I need to save some data, I create a TransactionScope object, save my data using Oracle ODP, then call the Complete method on my TransactionScope object and dispose the object itself:
public override bool Submit(ChangeSet changeSet)
{
TransactionOptions txopt = new TransactionOptions();
txopt.IsolationLevel = IsolationLevel.ReadCommitted;
using (TransactionScope tx = new TransactionScope(TransactionScopeOption.Required, txopt))
{
// Here I open an Oracle connection and fetch some data
GetSomeData();
// This is where I persist my data
result = base.Submit(changeSet);
tx.Complete();
}
return result;
}
My problem is, the first time I get the Submit method to be called, everything is fine, but if I call it a second time, the execution gets stuck for a couple of minutes after the call to Complete (so, when disposing tx), then I get the Oracle error "ORA-12154". Of course, I already checked that my persistence code completes without errors. Any ideas?
Edit: today I repeated the test and for some reason I'm getting a different error instead of the Oracle exception:
System.InvalidOperationException: Operation is not valid due to the current state of the object.
at System.Transactions.TransactionState.ChangeStatePromotedAborted(InternalTransaction tx)
at System.Transactions.InternalTransaction.DistributedTransactionOutcome(InternalTransaction tx, TransactionStatus status)
at System.Transactions.Oletx.RealOletxTransaction.FireOutcome(TransactionStatus statusArg)
at System.Transactions.Oletx.OutcomeEnlistment.InvokeOutcomeFunction(TransactionStatus status)
at System.Transactions.Oletx.OletxTransactionManager.ShimNotificationCallback(Object state, Boolean timeout)
at System.Threading._ThreadPoolWaitOrTimerCallback.PerformWaitOrTimerCallback(Object state, Boolean timedOut)
I somehow managed to solve this problem, although I still can't figure out the reason it showed up in the first place: I just moved the call to GetSomeData outside the scope of the distributed transaction. Since the call to Submit may open many connections and perform any kind of operations on the DB, I just can't tell why GetSomeData was causing this problem (it just opens a connection, calls a very simple stored function and returns a boolean). I can only guess that has something to do with the implementation of the Submit method and/or with the instantiation of multiple oracle connections within the same transaction scope.
I am currently using openRasta to build Rest Api.I am observing strange behavior while sending Ajax requests.Sometimes request is successful sometime it fails and it gives following exception.
{Exception:
System.Runtime.Serialization.SerializationException: Expecting element 'root' from namespace ''.. Encountered 'None' with name '', namespace ''.
at System.Runtime.Serialization.Json.DataContractJsonSerializer.InternalReadObject(XmlReaderDelegator xmlReader, Boolean verifyObjectName)
at System.Runtime.Serialization.XmlObjectSerializer.InternalReadObject(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.Json.DataContractJsonSerializer.ReadObject(XmlDictionaryReader reader)
at System.Runtime.Serialization.Json.DataContractJsonSerializer.ReadObject(Stream stream)
at OpenRasta.Codecs.JsonDataContractCodec.ReadFrom(IHttpEntity request, IType destinationType, String paramName)
at OpenRasta.OperationModel.Hydrators.RequestEntityReaderHydrator.TryReadPayloadAsObject(IHttpEntity requestEntity, IMediaTypeReader reader, IOperation operation)}
One thing i have observed is that when i keep browser idle for some time say more than 10 minutes i can see the request in firebug but it shows status as pending for long time and when it hits server it gives above exception.But same works fine sometimes.
Can anybody explain me this behavior?If want i can provide some additional code related to it.
The delay may just be caused by asp.net having to restart when you finally get out of idle, which takes a little while.
As for the error, it seems to be that the json data contract serializer can't parse the request. I'd advise to check a couple of things, and if it fails post here the details so we can help you further.
That the body is indeed correct at the time the error is triggererd (with fiddler)
That you do not have some asp.net-specific issues that would prevent the request from arriving correctly to the asp.net pipeline, such as cookies-based authentication or session management
That the request is not intercepted by any http module (anti forgery tokens etc).
Please provide your mappings, entities and a copy of the OR log (which you can get by attaching a debugger to the server process) and we'll try and help you further.