I have a hosted service sending messages to the client via SignalR and the client is picking them up and displaying on a razor page. Here is the stripped down version.
This works well except that the .js file is called AFTER the hosted service is instantiated which means the connection is not established in time for the first messages so these are lost.
Is there a way to check the connection using IHubContext before I send anything? Or do I need a more fundamental change to the whole approach?
Javascript (linked to the Index page)
"use strict";
var connection = new signalR.HubConnectionBuilder().withUrl("/logHub").build();
connection.start()
connection.on("ReceiveLogNotification", function (msg) {
console.log("JS: " + msg);
});
Hub class
public class LogHub : Hub
{
}
Hosted Service
public class MsgGenerator : IHostedService
{
private Random _random;
private Microsoft.Extensions.Logging.ILogger _logger;
private Timer? _timer;
private readonly IHubContext<LogHub> _hubContext;
public LogGenerator(ILogger<LogGenerator> logger,
IHubContext<LogHub> hubContext)
{
_logger = logger;
_random = new Random();
_timer = null;
_hubContext = hubContext;
}
public Task StartAsync(CancellationToken cancellationToken)
{
ScheduleNextMessage();
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
private void ScheduleNextMessage()
{
var nextTime = TimeSpan.FromMilliseconds(_random.Next(1000));
_timer = new Timer((state) => { GenerateMessage(); }, null, nextTime, TimeSpan.Zero);
}
private async void GenerateMessage()
{
await _hubContext.Clients.All.SendAsync("ReceiveLogNotification", "test message");
ScheduleNextMessage();
}
Related
I've developed a restful webservice which displays a simple data using below code.
package com.mike;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class MessageController {
#RequestMapping(value="/message",method=RequestMethod.GET)
public Message print(){
return new Message(1,"Hello Mike!!");
}
}
and the bean is as follows....
package com.mike;
public class Message {
private int id;
private String message;
public Message(int id, String message){
this.id=id;
this.message=message;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getMessage() {
return message;
}
public void setMesssage(String message) {
this.message = message;
}
}
now I want to display this data in an Nodejs application, so I wrote a file named app.js and wrote the following code to display data in the console.and it worked fine. but i don't know how to integrate this nodejs application with reactjs UI so that i can display in on a web page. so please kindly help me, I am new to both node and react.the code for app.js is below...
var http=require('http');
var extServerOptions={
host:'localhost',
port:'8080',
path:'/message',
method:'GET'
};
var mes=[];
var x;
var text="";
function get(){
http.request(extServerOptions,function (res){
res.setEncoding('utf8');
res.on('data',function(data){
mes=JSON.parse(data);
console.log(mes);
for(x in mes){
text+=mes[x]+" ";
};
console.log(text);
});
}).end();
};
get();
please kindly say me the stepps i need to do in order to display data in a react page.
I am just learning about Retrofit and Android development. What I would like to do is send a fairly complex JSON object to a server from a website and be able to retrieve it using Retrofit as a Java Object for my Android Application.
So basically something like this,
Website JSON --Ajax Call--> Server --Retrofit--> Android Application (Java Object / Collection)
Which server would be the best to set this up? Also are there any good references on how to accomplish this?
Thank you
With retrofit and android, you only need a couple of things
A java model
public class User {
private String name;
private String password;
public User(String name, String password) {
this.name = name;
this.password = password;
}
//Getters and setters
//...
}
A retrofit interface
public interface APIService {
#FormUrlEncoded
#Headers("Accept: application/json")
#POST("register")
Call<AuthRegister> createUser(
#Field("name") String name,
#Field("password") String password
);
}
A callback for retrofit
public class AuthRegister {
#SerializedName("message")
#Expose
private String message;
#SerializedName("errors")
#Expose
private Errors errors;
public String getMessage() {
return message;
}
public Errors getErrors() {
return errors;
}
}
A network client
public class NetworkClient {
public static Retrofit retrofit;
/*
This public static method will return Retrofit client
anywhere in the appplication
*/
public static Retrofit getRetrofitClient() {
//If condition to ensure we don't create multiple retrofit instances in a single application
if (retrofit == null) {
//Defining the Retrofit using Builder
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.level(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
// .addInterceptor(interceptor)
.connectTimeout(30, TimeUnit.MINUTES)
.build();
retrofit = new Retrofit.Builder()
.baseUrl(Config.BASE_URL) //This is the only mandatory call on Builder object.
.client(client)
.addConverterFactory(GsonConverterFactory.create()) // Convertor library used to convert response into POJO
.build();
}
return retrofit;
}
}
The call inside the activity you are to display the response or save the data
private void saveUser(String name, String password){
Retrofit retrofit = NetworkClient.getRetrofitClient();
APIService service = retrofit.create(APIService.class);
Call<AuthRegister> call = service.createUser(name, password);
call.enqueue(new Callback<AuthRegister>() {
#Override
public void onResponse(Call<AuthRegister> call, Response<AuthLogin> response) {
if (response.code() == 200) {
if (response.body().getMessage() != null) {
Toast.makeText(mContext, "Success", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(mContext, "Could not save user", Toast.LENGTH_LONG).show();
}
} else {
Toast.makeText(mContext, "Could not save user", Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(Call<AuthRegister> call, Throwable t) {
new PrefManager(mContext).clearUser();
Log.e(TAG, t.toString());
Toast.makeText(mContext, "Could not save user", Toast.LENGTH_SHORT).show();
}
});
}
You can use any server as you need. Any complex JSON can be handled by retrofit library. Check the Following link Retrofit android example web services
I have some issues developing my own plugin. I want my plugin to run as a background process on an android device. Searching the internet, I found using the Service superclass (or a sub-class) being most relevant. Below is some sample code, the execute method in Hello.java is successfully called - the app crashes when I try to start the service (the constructor is successfully instantiated though). Any hints?
//Myservice.java
public class MyService extends IntentService {
public MyService(String name) {
super(name);
Log.d("asd", "constructor");
}
#Override
public void onHandleIntent(Intent intent) {
Log.d("asd", "something");
}
}
//Hello.java
public class Hello extends CordovaPlugin {
#Override
public boolean execute(String action, JSONArray data, CallbackContext callbackContext) throws JSONException {
Log.d("asd", "we are in execute, hurray!");
Context context = cordova.getActivity().getApplicationContext();
Intent intent = new Intent(context, MyService.class);
MyService service = new MyService("WifiP2pService");
//either this
service.startService(intent);
//or this, tried both
//context.startService(intent);
return true;
}
}
// /plugins/the.package/www/hello.js
module.exports = {
greet: function (name, successCallback, errorCallback) {
cordova.exec(successCallback, errorCallback, "Hello", "greet", [name]);
}
};
// /www/index.js - in onDeviceReady function
var success = function(message) {
alert(message);
}
var failure = function() {
alert("Error calling the plugin");
}
hello.greet("Superdids", success, failure);
I am fairly new to android programming, so any hints would be muchly appreciated!
Blacklisting URLs in PhantomJS and GhostDriver is pretty straightforward. First initialize the driver with a handler:
PhantomJSDriver driver = new PhantomJSDriver();
driver.executePhantomJS(loadFile("/phantomjs/handlers.js"))
And configure the handler:
this.onResourceRequested = function (requestData, networkRequest) {
var allowedUrls = [
/https?:\/\/localhost.*/,
/https?:\/\/.*\.example.com\/?.*/
];
var disallowedUrls = [
/https?:\/\/nonono.com.*/
];
function isUrlAllowed(url) {
function matches(url) {
return function(re) {
return re.test(url);
};
}
return allowedUrls.some(matches(url)) && !disallowedUrls.some(matches(url));
}
if (!isUrlAllowed(requestData.url)) {
console.log("Aborting disallowed request (# " + requestData.id + ") to url: '" + requestData.url + "'");
networkRequest.abort();
}
};
I haven't found a good way to do this with HtmlUnitDriver. There's the ScriptPreProcessor mentioned in How to filter javascript from specific urls in HtmlUnit, but it uses WebClient, not HtmlUnitDriver. Any ideas?
Extend HtmlUnitDriver and implement a ScriptPreProcessor (for editing content) and a HttpWebConnection (for allowing/blocking URLs):
public class FilteringHtmlUnitDriver extends HtmlUnitDriver {
private static final String[] ALLOWED_URLS = {
"https?://localhost.*",
"https?://.*\\.yes.yes/?.*",
};
private static final String[] DISALLOWED_URLS = {
"https?://spam.nono.*"
};
public FilteringHtmlUnitDriver(DesiredCapabilities capabilities) {
super(capabilities);
}
#Override
protected WebClient modifyWebClient(WebClient client) {
WebConnection connection = filteringWebConnection(client);
ScriptPreProcessor preProcessor = filteringPreProcessor();
client.setWebConnection(connection);
client.setScriptPreProcessor(preProcessor);
return client;
}
private ScriptPreProcessor filteringPreProcessor() {
return (htmlPage, sourceCode, sourceName, lineNumber, htmlElement) -> editContent(sourceCode);
}
private String editContent(String sourceCode) {
return sourceCode.replaceAll("foo", "bar"); }
private WebConnection filteringWebConnection(WebClient client) {
return new HttpWebConnection(client) {
#Override
public WebResponse getResponse(WebRequest request) throws IOException {
String url = request.getUrl().toString();
WebResponse emptyResponse = new WebResponse(
new WebResponseData("".getBytes(), SC_OK, "", new ArrayList<>()), request, 0);
for (String disallowed : DISALLOWED_URLS) {
if (url.matches(disallowed)) {
return emptyResponse;
}
}
for (String allowed : ALLOWED_URLS) {
if (url.matches(allowed)) {
return super.getResponse(request);
}
}
return emptyResponse;
}
};
}
}
This enables both editing of content, and blocking of URLs.
In my index.html page, a variable in the script is hard coded. I want to get it from application.properties file but have no idea how to. It would helpful if anyone could provide me a solution.
I have attached the example. Hope to help.
Application
#SpringBootApplication
public class Application {
public static void main(String... args) {
SpringApplication.run(Application.class);
}
}
PropertiesController
#RestController
public class PropertiesController {
#Autowired
private UIProperty uiProperty;
#RequestMapping("properties")
public UIProperty getProperties() {
return uiProperty;
}
}
UIProperty
#Component
#ConfigurationProperties(prefix = "ui.label")
public class UIProperty {
private String user;
private String password;
public void setUser(String user) {
this.user = user;
}
public String getUser() {
return user;
}
public void setPassword(String password) {
this.password = password;
}
public String getPassword() {
return password;
}
}
application.properties
ui.label.user=user
ui.label.password=password
database.user=
database.password=
I'd create a RestController to expose ConfigurationProperties. But be sure to properly secure it as well as limit in its scope not to disclose confidential data like db access credentials.