I have made a jersey atmosphere service
When i am trying to subscribe the topic its get connected but its not receiving messages
i am trying to send messages from java client to javascript client
Server Code
#Path("/pubsub/{topic}")
public class Eventer {
private
#PathParam("topic")
Broadcaster topic;
#GET
public SuspendResponse<String> subscribe() {
return new SuspendResponse.SuspendResponseBuilder<String>()
.broadcaster(topic)
.outputComments(true)
.addListener(new EventsLogger())
.build();
}
#POST
#Broadcast
#Produces("text/html;charset=ISO-8859-1")
public Broadcastable publish(#FormParam("message") String message) {
return new Broadcastable(message, "", topic);
}
}
JavaScript client
var myName = false;
var author = null;
var logged = false;
var socket = $.atmosphere;
var subSocket;
var transport = 'websocket';
var fallbackTransport = 'long-polling'
var connected = false;
var uuid = 0;
function connect() {
// We are now ready to cut the request
var request = { url: 'http://localhost:8888/factory/factory/pubsub/Light_FF_Bath_Ceiling' ,
transport: transport,
fallbackTransport: fallbackTransport};
request.onOpen = function (response) {
alert('onOpen');
};
request.onReopen = function (response) {
alert('onReopen');
};
request.onMessage = function (response) {
alert(response);
};
request.onClose = function (response) {
subSocket.push(JSON.stringify({ author: author, message: 'disconnecting' }));
};
request.onError = function (response) {
alert('onError');
};
request.onReconnect = function (request, response) {
};
subSocket = socket.subscribe(request);
}
connect();
Web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- This web.xml file is not required when using Servlet 3.0 container,
see implementation details http://jersey.java.net/nonav/documentation/latest/jax-rs.html#d4e194 -->
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<description>AtmosphereServlet</description>
<display-name>AtmosphereServlet</display-name>
<servlet>
<description>AtmosphereServlet</description>
<servlet-name>AtmosphereServlet</servlet-name>
<servlet-class>org.atmosphere.cpr.AtmosphereServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<!-- If you want to use Servlet 3.0 -->
<async-supported>true</async-supported>
<!-- List of init-param -->
</servlet>
<servlet-mapping>
<servlet-name>AtmosphereServlet</servlet-name>
<!-- Any mapping -->
<url-pattern>/factory/*</url-pattern>
</servlet-mapping>
</web-app>
Related
Context:
We are using Websockets in our ASP.NET Core 2 MVC app. This is our code in our Startup.cs class:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
[...]
app.Use(async (context, next) =>
{
if (context.WebSockets.IsWebSocketRequest)
{
if(context.Request.Path == "/ws")
{
WebSocket lWebSocket = await context.WebSockets.AcceptWebSocketAsync();
// a custom class that handles the websocket request → perhaps replace by an action controller.
var lHandleWebSocket = new HandleWebSocket();
await lHandleWebSocket.HandleConnection(context, lWebSocket);
}
}
}
}
The data transfer will be handled by the class 'HandleConnection':
public async Task HandleConnection(HttpContext context, WebSocket pWebSocket)
{
var lBuffer = new byte[1024 * 4];
WebSocketReceiveResult lWebSocketReceiveResult = null;
string lTmpString = string.Empty;
// get next values
lWebSocketReceiveResult = await pWebSocket.ReceiveAsync(new ArraySegment<byte>(lBuffer), CancellationToken.None);
// Doing something here...
// close connection
await pWebSocket.CloseAsync(WebSocketCloseStatus.InternalServerError, "TestError", CancellationToken.None);
}
Here is a small snippet about the used JavaScript:
self.WebSocketChat = new WebSocket("ws://" + window.location.host + "/ws");
self.WebSocketChat.onclose = function (data) { console.log(data); };
self.WebSocketChat.onerror = function (data) { console.log(data); };
Description: The client connects with the server. When the client sends the first message to the Server, then the server closes the connection. In the client the 'onclose'-event fires as expected and prints the following information to the console:
Console: CloseEvent {isTrusted: true, wasClean: true, code: 1011, reason: "TestError", type: "close", …}
All is working as expected.
Problem:
Now we want to close the websocket connection when an exception occurs on server-side. We want to pass the message and callstack of the exception into the closing frame.
Catch Exceptions in the Startup.cs-File:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
[...]
app.Use(async (context, next) =>
{
if (context.WebSockets.IsWebSocketRequest)
{
if(context.Request.Path == "/ws")
{
WebSocket lWebSocket = await context.WebSockets.AcceptWebSocketAsync();
// a custom class that handles the websocket request → perhaps replace by an action controller.
var lHandleWebSocket = new HandleWebSocket();
try
{
await lHandleWebSocket.HandleConnection(context, lWebSocket);
}
catch (Exception e)
{
// close connection
await lWebSocket.CloseAsync(WebSocketCloseStatus.InternalServerError, e.ToString(), CancellationToken.None);
throw;
}
}
}
}
}
Throw an exception:
public async Task HandleConnection(HttpContext context, WebSocket pWebSocket)
{
var lBuffer = new byte[1024 * 4];
WebSocketReceiveResult lWebSocketReceiveResult = null;
string lTmpString = string.Empty;
// get next values
lWebSocketReceiveResult = await pWebSocket.ReceiveAsync(new ArraySegment<byte>(lBuffer), CancellationToken.None);
// throw an exception
throw new TestException("TestException");
}
When we send an message now to the server, the TestException will be thrown and catched as expected:
But on client-side the 'onclose'-Event does not fire.
self.WebSocketChat.onclose = function (data) { console.log(data); }; // nothing happens
Also the '.onerror' event does not fire.
Question:
How to close the Websocket connection when an exception occurs and pass the exception message to the client?
I am new to signalr,
I have gone through a number of tutorials where I have seen the chat room application where server has been configured on console app and client on javascript, as you open the multiple instances of browsers you can chat between them.
My question is how to chat between server to client rather than between clients.
lets say I build a server on winform. On that winform I have datagridview which shows me the number of clients connected to server and I want to send a message to client #2 , then the client #2 will also reply me which I will show in a textbox on winform.
My Client Code:
<script type="text/javascript">
$(function () {
$.connection.hub.url = "http://localhost:8080/signalr";
var chat = $.connection.myHub;
// Create a function that the hub can call to broadcast messages.
chat.client.addMessage = function (name, message) {
var encodedName = $('<div />').text(name).html();
var encodedMsg = $('<div />').text(message).html();
$('#discussion').append('<li><strong>' + encodedName
+ '</strong>: ' + encodedMsg + '</li>');
};
$('#displayname').val(prompt('Enter your name:', ''));
$('#message').focus();
$.connection.hub.start().done(function () {
$('#sendmessage').click(function () {
chat.server.send($('#displayname').val(), $('#message').val());
$('#message').val('').focus();
});
});
});
</script>
Myhub.cs:
public class MyHub : Hub
{
public void Send(string name, string message)
{
Clients.All.addMessage(name, message);
}
public void getname(string name)
{
}
public override Task OnConnected()
{
UserHandler.ConnectedIds.Add(Context.ConnectionId);
string RemoteIpAddress = Context.Request.GetRemoteIpAddress();
return base.OnConnected();
}
public override Task OnDisconnected(bool stopCalled)
{
UserHandler.ConnectedIds.Remove(Context.ConnectionId);
return base.OnDisconnected(stopCalled);
}
public void acknowledgment(string ack)
{
Clients.Caller.acknowledgment(ack);
}
}
Code seems good. try to add following code in startup.cs
app.Map("/signalr", map =>
{
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration
{
EnableJSONP = true
};
map.RunSignalR(hubConfiguration);
});
I am using the GuestController controller class. I going to access this GetGuestBookingIdByRoomId api method from the ajax as well as from the code behind file. This method returns proper result while ajax call but in code behind getting error with "StatusCode: 401, ReasonPhrase: 'Unauthorized'"
Api controller:
[Authorize]
public class GuestController : ApiController
{
public int GetGuestBookingIdByRoomId(int roomId)
{
return GuestManager.GetGuestBookingIdByRoomId(roomId);
} // GetGuestBookingIdByRoomId
}
Ajax call:
function getGuestBookingIdByRoomId(roomId) {
$.ajax({
url: _pageURL + "/api/Guest/GetGuestBookingIdByRoomId",
type: "GET",
data: { roomId: roomId },
dataType: "json",
success: function (bookingId) {
if (bookingId != undefined && bookingId != null && bookingId > 0) {
_receiverBookingId = bookingId;
} else {
// Do Nothing
}
},
});
}
api call from code behind:
private int GetReceiverBookingId(int roomId)
{
int receiverBookingId = 0;
// Create object of http client
HttpClient client = new HttpClient();
// assign Base address
client.BaseAddress = new Uri("http://" + Request.Url.Authority);
// Set request header
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// build web api url
var url = "/api/Guest/GetGuestBookingIdByRoomId?roomId=" + roomId;
// Call web api method
HttpResponseMessage response = client.GetAsync(url).Result;
if (response.IsSuccessStatusCode) // If web api call is successfull
{
receiverBookingId = response.Content.ReadAsAsync<int>().Result;
}
else
{
}
return receiverBookingId;
}
I get an "internal server error" (status code 500) when testing an ASP.NET Web API controller in an in-memory test.
[TestFixture]
public class ValuesControllerTest
{
private HttpResponseMessage response;
[TestFixtureSetUp]
public void Given()
{
var config = new HttpConfiguration
{
IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always
};
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { controller = typeof(ValuesController).Name.Replace("Controller", string.Empty), id = RouteParameter.Optional }
);
//This method will cause internal server error but NOT throw any exceptions
//Remove this call and the test will be green
ScanAssemblies();
var server = new HttpServer(config);
var client = new HttpClient(server);
response = client.GetAsync("http://something/api/values/5").Result;
//Here response has status code 500
}
private void ScanAssemblies()
{
PluginScanner.Scan(".\\", IsApiController);
}
private bool IsApiController(Type type)
{
return typeof (ApiController).IsAssignableFrom(type);
}
[Test]
public void Can_GET_api_values_5()
{
Assert.IsTrue(response.IsSuccessStatusCode);
}
}
public static class PluginScanner
{
public static IEnumerable<Type> Scan(string directoryToScan, Func<Type, bool> filter)
{
var result = new List<Type>();
var dir = new DirectoryInfo(directoryToScan);
if (!dir.Exists) return result;
foreach (var file in dir.EnumerateFiles("*.dll"))
{
result.AddRange(from type in Assembly.LoadFile(file.FullName).GetTypes()
where filter(type)
select type);
}
return result;
}
}
I have configured Visual Studio to break when any .Net exception is thrown. Code is not stopped at any exception nor can I find any exception details in the response.
What should I do to see what's causing the "internal server error"?
The exception is in Response.Content
if (Response != null && Response.IsSuccessStatusCode == false)
{
var result = Response.Content.ReadAsStringAsync().Result;
Console.Out.WriteLine("Http operation unsuccessful");
Console.Out.WriteLine(string.Format("Status: '{0}'", Response.StatusCode));
Console.Out.WriteLine(string.Format("Reason: '{0}'", Response.ReasonPhrase));
Console.Out.WriteLine(result);
}
You need to add a route so that it looks something like this:
var config = new HttpConfiguration()
{
IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always
};
config.Routes.MapHttpRoute(
name: "default",
routeTemplate: "api/{controller}/{id}",
defaults: new { controller = "Home", id = RouteParameter.Optional });
var server = new HttpServer(config);
var client = new HttpClient(server);
HttpResponseMessage response = client.GetAsync("http://somedomain/api/product").Result;
Btw, in the latest bits you get a 404 Not Found as you would expect.
Henrik
It sounds like you might have already found your answer, but that wasn't quite it for me so I want to add this for others with my issue.
To start out, it seems to be an issue with the new MVC 4 formatters. Setting any of the error policy flags will not work (IncludeErrorDetailPolicy, CustomErrors, etc), these formatters are ignoring them and just returning and empty "internal server error" 500.
I found this out by eventually overloading the formatters and checking their responses for errors:
public class XmlMediaTypeFormatterWrapper : XmlMediaTypeFormatter
{
public override Task WriteToStreamAsync(Type type, object value, Stream stream, HttpContentHeaders contentHeaders, TransportContext transportContext)
{
var ret = base.WriteToStreamAsync(type, value, stream, contentHeaders, transportContext);
if (null != ret.Exception)
// This means there was an error and ret.Exception has all the error message data you would expect, but once you return below, all you get is a blank 500 error...
return ret;
}
}
For now I am using Xml and Json formatter wrappers that simply look for ret.Exception and capture it so I at least have the data if a 500 happens. I couldn't really find an elegant way to make the error actually show up in the html response since Task.Exception is already set and this SHOULD be all the is required to pass the exception along.
I am trying to get a result from a webservice in an ASP.NET MVC (3) app. The webservice call (see below) works perfectly and I can see in Fiddler that I get a proper SOAP result back.
However, the call to "client.requestAuthorisation" results in a null. Am I missing something?
public static string GetToken()
{
var token = "";
var username = "user";
var password = "pass";
using (var client = new MvcApplication1.TheWebService.SingleSignOnSoapServerPortTypeClient())
{
using (new System.ServiceModel.OperationContextScope(client.InnerChannel))
{
var httpRequestProperty = new System.ServiceModel.Channels.HttpRequestMessageProperty();
var authenticationString = Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes(string.Format("{0}:{1}", username, password)));
httpRequestProperty.Headers[System.Net.HttpRequestHeader.Authorization] = string.Format("Basic {0}", authenticationString);
System.ServiceModel.OperationContext.Current.OutgoingMessageProperties[System.ServiceModel.Channels.HttpRequestMessageProperty.Name] = httpRequestProperty;
token = client.requestAuthorisation("admin");
}
}
return token;
}
The returned SOAP message is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="https://www.somedomain.ext" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns1:requestAuthorisationResponse>
<return xsi:type="xsd:string">6389a2dd8da662130e6ad1997267c67b043adc21</return>
</ns1:requestAuthorisationResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Have you tried regenerating the client code?