I have some angular code that asks for user name input:
playCtrl.js
var myApp = angular.module('myApp');
/*
* CONTROLLERS METHOD
*/
myApp.controller('PlayController', ['$scope', '$http', function($scope, $http) {
var REQUEST_SERVICE_URI = '/Project2/play.do';
//var REQUEST_SERVICE_URI = 'http://13.59.197.145:8085/Project2/#/play';
var playerObject = {} // create playerObject
$scope.message = "Let's play!";
$scope.message2 = "Please enter your name";
$scope.user = {
userid: '',
username: '',
roleId: '',
statusId: ''
};
$scope.register = function() {
playerObject = $scope.user; // adding user to a playerObject
console.log('playerObject.name: ' + playerObject.name);
//console.log('playerObject: ' + $scope.user.name);
console.log("REGISTER BUTTON WAS CLICKED");
$http.post(REQUEST_SERVICE_URI, playerObject).
then(function(playerObject) {
alert("SUCCESS");
//$scope.user = data;
});
}
}])
Then I have my SpringController.java that's trying to get this user object:
#RestController
public class SpringController {
// has to accept
#RequestMapping(headers="Accept=application/json", value="/play.do", method = RequestMethod.POST)
public String registerUser(Users user, BindingResult bindingResult, ModelMap modelMap, HttpSession session){
Register r = new Register();
System.out.println("TRYING TO CREATE A USER: " + user);
if(r.createUser(user.getUsername())){
session.setAttribute("username", user.getUsername());
session.setAttribute("role", user.getRole());
session.setAttribute("status", user.getStatus());
System.out.println("Created user: " + user.getUsername());
return "lobby";
}else{
return "login";
}
}
My console DOES print out everything in the angularjs perfectly fine, and it also prints "TRYING TO CREATE A USER: " + user from the java side, however it shoes that all everything is null: TRYING TO CREATE A USER: Users [userid=0, username=null, roleId=null, statusId=null]
(my user create implementation only needs a username, all others can be null)
Here's my web.xml:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/beans.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>SpringDispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/beans.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SpringDispatcher</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
Here's the error I get from the console:
javax.validation.ConstraintViolationException: Validation failed for classes
[com.revature.bean.Users] during persist time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
ConstraintViolationImpl{interpolatedMessage='Username cannot be empty(1-20 characters)', propertyPath=username, rootBeanClass=class com.revature.bean.Users, messageTemplate='Username cannot be empty(1-20 characters)'}
Users.java :
package com.revature.bean;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.validation.constraints.Size;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.stereotype.Component;
#Component
#Entity
#Table(name = "Users")
#Cache(usage = CacheConcurrencyStrategy.READ_ONLY, region = "myAwesomeCache")
public class Users {
#Id
#Column(name = "U_Id")
#SequenceGenerator(name = "UID_SEQ", sequenceName = "UID_SEQ")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "UID_SEQ")
private int userid;
#NotEmpty(message="Username cannot be empty(1-20 characters)")
#Size(min=1,max=20)
#Column(name = "Username")
private String username;
public Users() {
super();
}
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "Role_ID")
private Roles role;
#OneToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "Status_ID")
private Status status;
public Users(int userid, String username, Roles roleId, Status statusId) {
super();
this.userid = userid;
this.username = username;
this.role = roleId;
this.status = statusId;
}
public Users(String username, Roles roleId, Status statusId) {
super();
this.username = username;
this.role = roleId;
this.status = statusId;
}
public int getUserid() {
return userid;
}
public void setUserid(int userid) {
this.userid = userid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Status getStatusId() {
return status;
}
public void setStatusId(Status status) {
this.status = status;
}
public Roles getRole() {
return role;
}
public void setRole(Roles role) {
this.role = role;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
#Override
public String toString() {
return "Users [userid=" + userid + ", username=" + username + ", roleId=" + role + ", statusId=" + status
+ "]";
}
}
How would I go about sending the object properly?
I just figured it out: I had to add #RequestBody within the () of my SpringController method, and change the input from Object to String type:
public String registerUser(#RequestBody String username, BindingResult bindingResult, ModelMap modelMap, HttpSession session)
Related
I put this.useraccountsubject(user) to interpolate information on login, but I get an error :
ErrorType: this.useraccount.next(user) then Error An argument of type 'HttpResponse' is not
allowed against a balance of 'Useraccount'
auth service.ts :
export class AuthService {
private useraccountSubject: BehaviorSubject<Useraccount> =
new BehaviorSubject<Useraccount>(new Useraccount("", "", "", "", ""));
public user: Observable<Useraccount> =
this.useraccountSubject.asObservable();
isLoggedIn = new BehaviorSubject(false);
constructor(private http:HttpClient, private router:Router){
this.useraccountSubject =
new BehaviorSubject<Useraccount>(null as any);
this.user = this.useraccountSubject.asObservable();
if(sessionStorage.getItem("USER")){
const user =sessionStorage.getItem("USER");
if(user){
this.useraccountSubject.next(JSON.parse(user));
}
}
}
private handleError(err: HttpErrorResponse) {
if (err.status === 200) {
console.error('Error:',err.error.data)
} else {
console.error(`Backend error ${err.status}`)
}
return throwError(err);
}
private handleErrorsingup(err: HttpErrorResponse) {
if (err.status === 201) {
console.error('Error:',err.error.data)
} else {
alert('faild');
console.error(`Backend error ${err.status}`)
}
return throwError(err);
}
login(username:string,password:string){
const params = new FormData();
params.append('username', username);
params.append('password', password);
return this.http.post<any>(`${baseUrl}/signin/`, params, { observe:'body', withCredentials: true})
.pipe(map(user=>{
catchError(this.handleError)
//edit !!
this.useraccountSubject.next(user);
sessionStorage.setItem("USER", JSON.stringify(user));
this.isLoggedIn.next(true);
return user;
}));
}
signup(email:string,password:string,name:string ){
const params = new FormData();
params.append('email', email);
params.append('password', password);
params.append('name', name);
return this.http.post<any>(`${baseUrl}/signup/`, params, { observe:'body', withCredentials: true })
.pipe(
catchError(this.handleErrorsingup)
);
}
logout(){
return this.http.post<any>(`${baseUrl}/signout/`, {})
.subscribe(response => {
this.isLoggedIn.next(false);
this.useraccountSubject.next(null as any)
sessionStorage.clear();
this.router.navigate(['login'])
})
}
//edit
setUseraccount(user: Useraccount): void {
this.useraccountSubject.next(user);
}
getUseraccount(): Observable<Useraccount> {
return this.useraccountSubject;
}
}
The format 'HttpResponse' does not have id, username, name, password, email attributes in the format 'Useraccount'.
Useraccount.ts:
export class Useraccount{
constructor(
public id:string,
public username: string,
public name: string,
public password: string,
public email: string
){}
}
I have for that format Useracount.ts
header.ts
export class HeaderComponent implements OnInit {
private userSubject: BehaviorSubject<Useraccount> = new
BehaviorSubject<Useraccount>(new Useraccount("", "", "", "", ""));
user:Observable<Useraccount> = this.userSubject.asObservable();
loginStatus?: boolean;
constructor(private authservice:AuthService) {
}
ngOnInit(): void {
this.authservice.getUseraccount().subscribe(res => {
if (res === null) {
// handler error
console.log(this.user);
} else {
let useraccountSubject: Useraccount = new Useraccount(res.id, res.username, res.email, res.password, res.name);
this.userSubject.next(useraccountSubject);
}
});
this.authservice.isLoggedIn.subscribe((status:any) => {
this.loginStatus = status;
});
}
logout($event: any){
$event.stopPropagation();
this.authservice.logout();
}
}
header.html
<ul class="info_ul" *ngIf="!loginStatus" >
<li><a routerLink='/login' >login</a></li>
<li><a routerLink='/singup' >signup</a></li>
</ul>
<ul class="info_ul" *ngIf="loginStatus">
<div *ngIf="user | async"> //edit
<li>{{( user | async).username }}</li> //username . string error
</div>
<li><a (click)="logout($event)">logout</a></li>
</ul>
console
user: {id: 7, uuid: '11a25078-be87-4a53-9ff7-ead8777f79be', username:
'bb#test.kr', email: 'bb#test.kr', name: 'beom', …}
[[Prototype]]: Object
The error is gone but the username is interpolated and doesn't appear in the header Could you please take a look at this issue?
It's probably a problem with the types
try this adjustments to your code
First change User Class:
export class Useraccount {
constructor(
public id:string,
public username: string,
public name: string,
public password: string,
public email: string
){}
}
In AuthService :
private currentUser: BehaviorSubject<Useraccount> =
new BehaviorSubject<Useraccount>(new Useraccount("", "", "", "", ""));
login(username:string,password:string){
const params = new FormData();
params.append('username', username);
params.append('password', password);
return this.http.post<any>(`${baseUrl}/signin/`, params, { observe:'body', withCredentials: true})
.pipe(
catchError(this.handleErrorsingup)
);
}
logout(){
return this.http.post<any>(`${baseUrl}/signout/`, {})
.subscribe(response => {
this.isLoggedIn.next(false);
this.setCurrentUser(null);
sessionStorage.clear();
this.router.navigate(['login'])
}
In auth.serice create two new functions :
setCurrentUser(user: Useraccount): void {
this.currentUser.next(user);
}
getCurrentUser(): Observable<Useraccount> {
return this.currentUser;
}
In the header do this :
export class HeaderComponent implements OnInit {
user: Useraccount = new Useraccount("", "", "", "", "");
private userNameSubject: BehaviorSubject<string> = new BehaviorSubject<string>("");
userName$: Observable<string> = this.userNameSubject.asObservable();
loginStatus?: boolean;
constructor(private authservice:AuthService) { }
ngOnInit(): void {
this.authservice.getCurrentUser().subscribe(res => {
if (res === null) {
// handler error
console.log(this.user);
} else {
this.userNameSubject.next(res.username);
this.user = new Useraccount(res.userId, res.username, ...);
}
})
this.authservice.isLoggedIn.subscribe((status:any) => {
this.loginStatus = status;
});
}
logout($event: any){
$event.stopPropagation();
this.authservice.logout();
this.user = new Useraccount("", "", "", "", "");
}
}
<ul class="info_ul" *ngIf="!loginStatus" >
<li><a routerLink='/login' > 로그인</a></li>
<li><a routerLink='/singup' >회원가입</a></li>
</ul>
<ul class="info_ul" *ngIf="loginStatus">
<ng-container>
<li>{{ userName$ | async }}</li>
</ng-container>
<li><a (click)="logout($event)">로그아웃</a></li>
</ul>
I can't comment yet, so writing here.
I think its type cast issue. In the next method on BehaviorSubject, try creating Useraccount object for your data like
this.useraccountSubject.next(new Useraccount(user));
PS, in case it doesn't work try to use Useraccount as Interface.
The problem is in this line
this.http.post<any>(`${baseUrl}/signin/`, params, {observe:'response', withCredentials: true})
The value of observe should be body
this.http.post<Useraccount>(`${baseUrl}/signin/`, params, {observe:'body', withCredentials: true})
Look at Overload #15 in this (https://angular.io/api/common/http/HttpClient#post)
I have a small web app built using Spring, and the REST services are accessible from curl and postman. If I try to access them using the JavaScript hosted on my web app I get a 405 error. What could cause this?
I realize there are insecurities in the code, this is just a rushed class project so they are not important.
If I copy the JavaScript code and run it in the console of the browser it works.
User class
import org.springframework.data.annotation.Id;
public class User {
#Id
public String id;
private String username;
private String firstName;
private String lastName;
private String password;
private int zipCode;
private int jacketThreshold;
private int coatThreshold;
public User() {}
public User(String username)
{
this.username = username;
}
public User(String firstName, String lastName, String password) {
this.firstName = firstName;
this.lastName = lastName;
this.password = password;
}
public User(String username, String password, int zipCode) {
this.username = username;
this.password = password;
this.zipCode = zipCode;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getZipCode() {
return zipCode;
}
public void setZipCode(int zipCode) {
this.zipCode = zipCode;
}
public int getJacketThreshold() {
return jacketThreshold;
}
public void setJacketThreshold(int jacketThreshold) {
this.jacketThreshold = jacketThreshold;
}
public int getCoatThreshold() {
return coatThreshold;
}
public void setCoatThreshold(int coatThreshold) {
this.coatThreshold = coatThreshold;
}
#Override
public String toString() {
return String.format(
"User[id=%s, firstName='%s', lastName='%s']",
id, firstName, lastName);
}
}
UserController class
import org.springframework.web.bind.annotation.*;
#RestController
public class UserController {
private final UserRepository repository;
public UserController(UserRepository repository) {
this.repository = repository;
}
#CrossOrigin
#PostMapping("/newuser")
User newUser(#RequestBody User newUser)
{
return repository.save(newUser);
}
}
UserRepository
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
#RepositoryRestResource(collectionResourceRel = "users", path = "users")
public interface UserRepository extends MongoRepository<User, String> {
public User findByUsername(#Param("username") String username);
}
Application class
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class WtwApplication {
public static void main(String[] args) {
SpringApplication.run(WtwApplication.class, args);
}
}
JavaScript calling the REST service
var user = document.getElementById('uname');
var pass = document.getElementById('pass');
var zip = document.getElementById('zip');
const data = { username : user, password : pass};
fetch('http://localhost:8080/newuser', {
method: 'POST', // or 'PUT'
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data),
})
.then(response => response.json())
.then(data => {
console.log('Success:', data);
})
.catch((error) => {
console.error('Error:', error);
});
Error received
2020-12-04 22:52:34.071 WARN 17936 --- [nio-8080-exec-7] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported]
Cross origin must include your js hosted server address like
Ex - #CrossOrigin(origins="http://localhost:3000)
and add it after the #RestController
Check your js code.
If you look at your controller, it's declared #PostMapping. Make sure your js code is calling the same POST method.
Check if you are returning a #ResponseBody or a #ResponseStatus
To fix this simply add a #ResponseBody
#RequestMapping(value="/user", method = RequestMethod.POST)
public #ResponseBody String updateUser(#RequestBody User user){
return userService.updateUser(user).getId();
}
or a #ResponseStatus to your method.
#RequestMapping(value="/user", method = RequestMethod.POST)
#ResponseStatus(value=HttpStatus.OK)
public String updateUser(#RequestBody User user){
return userService.updateUser(user).getId();
}
When I'm trying to subsrcibe to a post request, it always returns the TypeError: result is null
I'm using a Angular CLI that connects with a Spring boot application, with a simple login page. Where I want to save the header of my response in local storage
This is the stacktrace:
"LoginComponent.prototype.login/<#webpack-internal:///../../../../../src/app/components/login/login.component.ts:32:13\nSafeSubscriber.prototype.__tryOrUnsub#webpack-internal:///../../../../rxjs/_esm5/Subscriber.js:245:13\nSafeSubscriber.prototype.next#webpack-internal:///../../../../rxjs/_esm5/Subscriber.js:192:17\nSubscriber.prototype._next#webpack-internal:///../../../../rxjs/_esm5/Subscriber.js:133:9\nSubscriber.prototype.next#webpack-internal:///../../../../rxjs/_esm5/Subscriber.js:97:13\nMapSubscriber.prototype._next#webpack-internal:///../../../../rxjs/_esm5/operators/map.js:88:9\nSubscriber.prototype.next#webpack-internal:///../../../../rxjs/_esm5/Subscriber.js:97:13\nFilterSubscriber.prototype._next#webpack-internal:///../../../../rxjs/_esm5/operators/filter.js:92:13\nSubscriber.prototype.next#webpack-internal:///../../../../rxjs/_esm5/Subscriber.js:97:13\nMergeMapSubscriber.prototype.notifyNext#webpack-internal:///../../../../rxjs/_esm5/operators/mergeMap.js:156:13\nInnerSubscriber.prototype._next#webpack-internal:///../../../../rxjs/_esm5/InnerSubscriber.js:27:9\nSubscriber.prototype.next#webpack-internal:///../../../../rxjs/_esm5/Subscriber.js:97:13\nonLoad#webpack-internal:///../../../common/esm5/http.js:2310:21\nZoneDelegate.prototype.invokeTask#webpack-internal:///../../../../zone.js/dist/zone.js:421:17\nonInvokeTask#webpack-internal:///../../../core/esm5/core.js:4939:24\nZoneDelegate.prototype.invokeTask#webpack-internal:///../../../../zone.js/dist/zone.js:420:17\nZone.prototype.runTask#webpack-internal:///../../../../zone.js/dist/zone.js:188:28\nZoneTask.invokeTask#webpack-internal:///../../../../zone.js/dist/zone.js:496:24\ninvokeTask#webpack-internal:///../../../../zone.js/dist/zone.js:1517:9\nglobalZoneAwareCallback#webpack-internal:///../../../../zone.js/dist/zone.js:1543:17\n"
This is my login.service.ts:
const httpOptions = { headers: new HttpHeaders({'Content-type': 'application/json'}) };
#Injectable() export class LoginService {
private loginUrl = 'https://music-makers.herokuapp.com/login';
constructor(private http: HttpClient) { }
public login(user: User): Observable<any> {
return this.http.post(this.loginUrl, user, httpOptions); }
And my login.components.ts:
export class LoginComponent implements OnInit {
model: any = {};
constructor(private loginService: LoginService, public router: Router) {
}
ngOnInit() {
}
login() {
const user = <User>({
email: this.model.email,
password: this.model.password,
});
console.log('email: ' + user.email + '\npass: ' + user.password);
this.loginService.login(user)
.subscribe(
result => {
// Handle result
localStorage.setItem('Authorization', result.headers.get('Authorization'));
console.log(result);
},
error => {
// Handle error
console.log('Error');
},
() => {
console.log('complete');
// No errors, route to new page
}
);
}
}
Your service should be use map() to return as an observable collection
public login(user: User): Observable<any> {
return this.http.post(this.loginUrl, user, httpOptions)
.map(responce => <any>responce)
.catch(error => {
return Observable.throw(error);
});
}
I have a simple MVC Get method as below to get a Customer Id from the Session
[HttpGet]
public string GetCustomerId()
{
return Session["CUSTOMERID"].ToString();
}
If I hit this URL directly in the browser
http://localhost/myApp/Home/GetCustomerId I can set a breakpoint int the method and it gets hit and I get the value returned.
However, I need to call the method from my Client code which is Angular 2 written in typescript. My Typescript method is as below - I cannot get it to hit the MVC Breakpoint even though I am logging the exact same URL as above to the console.
public getCustomerIdFromSession() {
console.log('get customer from session called');
let srv = this.environmentService.getCurrentEnvironment();
let httpOrHttps = '';
if (srv === AppSettings.ENV_LOCALHOST) {
httpOrHttps = AppSettings.URL_HTTP;
}
else {
httpOrHttps = AppSettings.URL_HTTPS;
}
let baseUrl = httpOrHttps + srv + AppSettings.URL_GET_CUST_FROM_SESSION;
console.log(baseUrl); //this logs - http://localhost/myApp/Home/GetCustomerId
return this.http.get(baseUrl)
.catch(this.handleError);
}
public handleError(error: Response) {
console.log("error");
return Observable.throw(error.json() || 'Server Error');
}
**UPDATE To include entire Typescript service
import { Injectable, Output, EventEmitter } from '#angular/core';
import { Http, Response, RequestOptions, Headers } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import { EnvironmentService } from '../common/environment.service';
import { AppSettings } from '../common/app-settings';
#Injectable()
export class SessionService {
#Output() public gSession: EventEmitter<any> = new EventEmitter();
private sessionTime: number = 1500000; // 25 minute
constructor(private http: Http, private environmentService: EnvironmentService) {
}
public setValue(isLoading: boolean): void {
this.gSession.emit(isLoading);
}
public getValue(): any {
return this.gSession;
}
public startSession(): void {
this.getCustomerIdFromSession();
let timeoutId = setTimeout(() => {
this.setValue(true);
}, this.sessionTime);
}
public getCustomerIdFromSession() {
console.log('get customer from session called');
let srv = this.environmentService.getCurrentEnvironment();
let httpOrHttps = '';
if (srv === AppSettings.ENV_LOCALHOST) {
httpOrHttps = AppSettings.URL_HTTP;
}
else {
httpOrHttps = AppSettings.URL_HTTPS;
}
let baseUrl = httpOrHttps + srv + AppSettings.URL_GET_CUST_FROM_SESSION;
console.log(baseUrl); //this logs - http://localhost/myApp/Home/GetCustomerId
return this.http.get(baseUrl)
.catch(this.handleError);
}
public handleError(error: Response) {
console.log("error");
return Observable.throw(error.json() || 'Server Error');
}
public extractData(res: Response) {
console.log("In extract method");
let body = res.json();
console.log(body);
if (body) {
return body.data || body;
} else {
return {};
}
}
}
You are not mapping the response.
return this.http
.get(baseUrl)
.map(this.extractData)
.catch(this.handleError);
private extractData(res: Response) {
let body = res.json();
if (body) {
return body.data || body;
} else {
return {};
}
}
You have to map the response and process it with json() if you know that will be a JSON or with text(). Usually will be JSON.
I took the liberty of adding a response handler such as extractData. You could just json() the response directly if you wanted.
I am building a chat app. I have a client (Ionic 2) talking to a server (Java). The client can receive messages successfully from the server (e.g. "Welcome to the chat!" is received when connecting), but when I try send a message to the server from the client, it does not get there (the DataListener<Message> is not being invoked on the "chat_message:send" event.).
Please any suggestions?
Server Code:
import com.corundumstudio.socketio.AckRequest;
import com.corundumstudio.socketio.Configuration;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.listener.ConnectListener;
import com.corundumstudio.socketio.listener.DataListener;
import com.corundumstudio.socketio.listener.DisconnectListener;
public class Server {
public static void main(String[] args) {
Configuration config = new Configuration();
config.setHostname("localhost");
config.setPort(3700);
final SocketIOServer server = new SocketIOServer(config);
server.addConnectListener(new ConnectListener() {
#Override
public void onConnect(SocketIOClient client) {
System.out.println("onConnected");
client.sendEvent("chat_message:message", new Message("Welcome to the chat!"));
}
});
server.addDisconnectListener(new DisconnectListener() {
#Override
public void onDisconnect(SocketIOClient client) {
System.out.println("onDisconnected");
}
});
server.addEventListener("chat_message:send", Message.class, new DataListener<Message>() {
#Override
public void onData(SocketIOClient client, Message data, AckRequest ackSender) throws Exception {
System.out.println("onSend: " + data.toString());
server.getBroadcastOperations().sendEvent("chat_message:message", data);
}
});
System.out.println("Starting server...");
server.start();
System.out.println("Server started");
}
}
and
public class Message {
private String message;
public Message(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
Client Code:
import { Component, NgZone } from '#angular/core';
import { Http } from "#angular/http";
import { MessageModel } from '../model/messageModel';
import { UtilityService } from '../utils/utilityService';
declare var io;
#Component({
templateUrl: 'build/pages/chat/chat.html',
providers: [UtilityService]
})
export class ChatPage {
private socketHost: string = "http://localhost:3700";
private messages: MessageModel[] = [];
private zone: NgZone = null;
private chatBox: string = null;
private socket: any = null;
private utilityService: UtilityService = null;
constructor(http: Http, utilityService: UtilityService) {
this.utilityService = utilityService;
this.setUpMessageService(http);
}
setUpMessageService(http: Http): void {
this.messages = [];
this.zone = new NgZone({ enableLongStackTrace: false });
let url = this.socketHost + "/fetch";
http.get(url).subscribe((success) => {
var data = success.json();
console.log(data);
for (var i = 0; i < data.length; i++) {
this.messages.push(data[i].message);
}
}, (error) => {
console.log(JSON.stringify(error));
});
this.chatBox = "";
this.socket = io(this.socketHost);
this.socket.on("chat_message:message", (messageModel: MessageModel) => {
this.zone.run(() => {
console.log('run: ' + messageModel);
this.messages.push(messageModel);
});
});
}
send(msg) {
if (msg && msg != "") {
let messageModel: MessageModel = new MessageModel();
messageModel.message = msg;
console.log(messageModel);
this.socket.emit("chat_message:send", messageModel);
}
this.chatBox = "";
}
}
and
import { Injectable } from "#angular/core";
#Injectable()
export class MessageModel {
public message: string = null;
}
If I send the message as a String and not a MessageModel from the client it works.