Spring + React fetch data - json

i have a problem with fetch data from api exposed by spring.
I want to fetch data by:
componentDidMount() {
this.setState({isLoading: true});
fetch('http://localhost:8080/api/tasks/')
.then(response => { return response.json() })
.then(results => this.setState({
tasks: results,
isLoading: false
}));
The spring api which return data:
#CrossOrigin(origins = "http://localhost:3000")
#GetMapping
public List<Task> findTasksByUserId() {
return taskService.findTasksBelongToUser(idProvider.getCurrentUserId());
}
Returned JSON:
[
{
id: 1,
version: 0,
name: "Task1",
description: "description1",
priority: 1,
finished: true,
category: {
id: 1,
version: 0,
name: "Uncategorized",
user: {
id: 1,
version: 0,
login: "admin",
email: "admin#todo.pl",
enabled: true
}
},
user: {
id: 1,
version: 0,
login: "admin",
email: "admin#todo.pl",
enabled: true
},
position: 0
},
{
id: 2,
version: 0,
name: "Task2",
description: "description2",
priority: 4,
finished: true,
category: {
id: 1,
version: 0,
name: "Uncategorized",
user: {
id: 1,
version: 0,
login: "admin",
email: "admin#todo.pl",
enabled: true
}
},
user: {
id: 1,
version: 0,
login: "admin",
email: "admin#todo.pl",
enabled: true
},
position: 1
}]
And i got a error like this:
Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0
I dont know what is wrong but maybe format of json is not correct, because it's start with the sign '['.
I am a beginner in React so please about some hint and help.
regards

fetch() returns a promise which gets resolved into an HTTP response of course, not the actual JSON. To extract the JSON body content from the response, we use the json() method.
Try adding two headers Content-Type and Accept to be equal to application/json.
fetch('http://localhost:8080/api/tasks/', {
headers : {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
})
.then(response => { return response.json() })
.then(results => this.setState({
tasks: results,
isLoading: false
}));

Related

Sequelize findAll not returning expected output on sequelize-mock

I'm trying to do unit testing on my nodejs-express method with sequelize-mock.
Controller
const getDetailsByUserId = async (id) => {
try {
const userId = id ?? 0;
const details = await Model.findAll(
{
raw: true,
where: { user_id: userId }
}
);
if (details && details .length > 0) {
return {
status: 200,
success: true,
message: 'details found.',
data: details
}
}
return {
status: 404,
success: false,
message: 'details not found',
data: []
}
} catch (error) {
return {
status: 500,
success: false,
message: error.message || "An error occurred while getting details.",
data: null
}
}
}
Test
jest.mock('../models/details', () => () => {
const SequelizeMock = require("sequelize-mock");
const dbMock = new SequelizeMock();
return dbMock.define('users', [
{
id: 1,
user_id: 123
name: 'John Doe 1'
},
{
id: 2,
user_id: 456
name: 'John Doe 2'
},
{
id: 3,
user_id: 789
name: 'John Doe 3'
}
]);
});
test('should return 404 and an empty array', async () => {
const userId = 147;
const details = await controller.getDetailsByUserId(userId);
expect(details.status).toEqual(404);
});
I always get the status of 200 instead of 404 here. I checked the returned data and it's returning the records of the defined mocked model.
Actual Result:
[
fakeModelInstance {
options: {
timestamps: true,
paranoid: undefined,
createdAt: undefined,
updatedAt: undefined,
deletedAt: undefined,
isNewRecord: true
},
_values: {
'0': [Object],
'1': [Object],
'2': [Object],
user_id: 147,
id: 1,
createdAt: 2021-09-18T00:55:25.976Z,
updatedAt: 2021-09-18T00:55:25.976Z
},
dataValues: {
'0': [Object],
'1': [Object],
'2': [Object],
user_id: 147,
id: 1,
createdAt: 2021-09-18T00:55:25.976Z,
updatedAt: 2021-09-18T00:55:25.976Z
},
hasPrimaryKeys: true,
__validationErrors: []
}
]
QUESTIONS:
Is there something I can do to get the expected result (empty array) for this scenario?
the raw: true seems to be not working when it is mocked. Is there a way could log the result on raw object?
NOTE: This only happens on the unit testing. When accessing the endpoint on postman it returns the expected result.
According to the docs, findAll() will always return an array of a single result based on the where query in the options. This is why you will never get an empty array.
See more: https://sequelize-mock.readthedocs.io/en/stable/api/model/#findalloptions-promisearrayinstance

error: SequelizeValidationError: string violation: created cannot be an array or an object

I am implementing MERN Stack Login / Registration and trying to test my response in Postman step by step. Firstly, I written the code for Registration then for Login but in case of calling registration link I am getting the following error in postman:
error: SequelizeValidationError: string violation: created cannot be an array or an object
Can someone provide any suggestions to help? I think in User.js findone() function is having some sort of miss from my side.
Could there be any other solution?
./database/DB.js
const db = {}
const sequelize = new Sequelize("mern", "root", "", {
host: "localhost",
dialect: "mysql",
port: "3307",
operatorsAliases: false,
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
}
})
db.sequelize = sequelize
db.sequelize = sequelize
module.exports = db
./models/User.js
const db = require("../database/db")
module.exports = db.sequelize.define(
'user',
{
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
first_name: {
type: Sequelize.STRING
},
last_name: {
type: Sequelize.STRING
},
email: {
type: Sequelize.STRING
},
password: {
type: Sequelize.STRING
},
created: {
type: Sequelize.STRING
}
},
{
timestamps: false
}
);
./routes/User.js
const users = express.Router()
const cors = require('cors')
const jwt = require("jsonwebtoken")
const bcrypt = require('bcrypt')
const User = require("../models/User")
users.use(cors())
process.env.SECRET_KEY = 'secret'
users.post('/register', (req, res) => {
const today = new Date()
const userData = {
first_name: req.body.first_name,
last_name: req.body.last_name,
email: req.body.email,
password: req.body.password,
created: today
}
User.findOne({
where: {
email: req.body.email
}
})
.then(user => {
if(!user){
bcrypt.hash(req.body.password, 10, (err, hash) => {
userData.password = hash
User.create(userData)
.then(user => {
res.json({status: user.email + ' registered'})
})
.catch(err => {
res.send('error: ' + err)
})
})
} else {
res.json({error: "User already exists"})
}
})
.catch(err => {
res.send('error: ' + err)
})
})
users.post('/login', (req, res) => {
User.findOne({
where: {
email: req.body.email
}
})
.then(user => {
if(user) {
if(bcrypt.compareSync(req.body.password, user.password)) {
let token = jwt.sign(user.dataValues, process.env.SECRET_KEY, {
expiresin: 1440
})
res.send(token)
}
} else {
res.status(400).json({error: 'User does not exist'})
}
})
.catch(err => {
res.status(400).json({ error: err})
})
})
module.exports = users
package.json
"name": "login-registration",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "nodemon server.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"bcrypt": "^3.0.6",
"bcryptjs": "^2.4.3",
"body-parser": "^1.17.2",
"cors": "^2.8.4",
"express": "^4.16.3",
"jsonwebtoken": "^7.4.2",
"mysql": "^2.14.1",
"mysql2": "^1.6.1",
"nodemon": "^1.18.3",
"sequelize": "^4.38.0"
}
}
Server.js
var cors = require ('cors')
var bodyParser = require("body-parser")
var app = express()
var port = process.env.PORT || 5000
app.use(bodyParser.json())
app.use(cors())
app.use(bodyParser.urlencoded({extended: false}))
var Users = require('./routes/users')
app.use('/users', Users)
app.listen(port, () => {
console.log("Server is running at port: " + port)
})
In ./routes/User.js, under the /post register route, the userData object has a created field with today property which is a Date object.
In ./models/User.js you specify that created should have type Sequelize.STRING.
This is the contradiction that is causing the error. When you call User.create(userData), it gives you that error because the input parameter is of the wrong type.
To fix this, you either need to have created expect a type of Sequlize.Date or convert the today date object to a string.
const today = new Date().toJSON();
There are many different to string functions for the Date class. You should pick the one that best suits you here
This error is as a result of submitting a value of a wrong type compared to the
one declared in the model. Therefore, change it to the appropriate
type which is "JSON" instead of "STRING".
./models/User.js
const db = require("../database/db")
module.exports = db.sequelize.define(
'user',
{
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
first_name: {
type: Sequelize.STRING
},
last_name: {
type: Sequelize.STRING
},
email: {
type: Sequelize.STRING
},
password: {
type: Sequelize.STRING
},
created: {
type: Sequelize.JSON
}
},
{
timestamps: false
}
);
Its the "today" attribute that's causing the issue, you are trying to save a date obj instead of string. Change it to string while saving.

Can't connect to the local MySQL in Sails v1.0

I'm new to Sails and currently working on connection between Sails project and MySQL. I found that the 'Client Connection' on MySQL Workbench doesn't show any connection after my sails lift and I can't get any data from MySQL also.
[config/datastores.js]
module.exports.datastores = {
default: {
adapter: require('sails-mysql'),
url: 'mysql://root:pw#localhost:3306/database',
}
};
[api/model]
module.exports = {
attributes: {
'username': {
type: 'string',
},
'email': {
type: 'string',
},
'password': {
type: 'string',
},
'create_time': {
type: 'string',
},
},
};
[api/devController]
module.exports = {
index: function(req,res){
model.find().exec(function(err,info){
return res.json(info);
});
},
};
After sails lift, the json return empty.Is that something missing or wrong?

GraphQL error update mutation "Resolve function for \"User.id\" returned undefined"

I am a newbie to GraphQL and trying to write an update mutation. However, I am receiving Resolve function for \"User.id\" returned undefined" error although the database is actually got updated.
What am I doing wrong?
userSchema.js:
import Sequelize from 'sequelize';
import SqlHelper from '../helpers/sqlhelper';
const config = require('../../config');
const sequelizer = new SqlHelper(config).Init();
const createUser = sequelizer.define(
'createUser',
{
...
}
);
const updateUser = sequelizer.define(
'updateUser',
{
id: {
type: Sequelize.UUID,
field: 'Id',
primaryKey: true,
defaultValue: Sequelize.UUIDV4,
},
username: {
type: Sequelize.STRING,
field: 'Username',
allowNull: true,
},
email: {
type: Sequelize.STRING,
field: 'Email',
allowNull: true,
},
firstname: {
type: Sequelize.STRING,
field: 'FirstName',
allowNull: true,
},
lastname: {
type: Sequelize.STRING,
field: 'LastName',
allowNull: true,
},
....
},
{
// define the table's name
tableName: 'Users',
},
);
module.exports = User;
UserResolver.js:
import User from '../dbschemas/user';
import Sequelize from 'sequelize';
const Op = Sequelize.Op;
export default {
Mutation: {
createUser: async (obj, args) =>
(await User.create(args)),
updateUser: async (obj, args) =>
(await User.update(args,
{
where: {
id: args.id,
},
returning: true
}))
}
};
Although calling updateUser from GraphiQL updates the records (in db), it results in a "Resolve function for \"User.id\" returned undefined" error:
mutation{
updateUser(id: "2ecd38ca-cf12-4e79-ac93-e922f24af9e3",
username: "newUserTesting",
email: "testemail#yahoo.com",
lastname: "TestUserLName",
firstname: "fname1") {
id
}
}
{
"data": null,
"errors": [
{
"message": "Resolve function for \"User.id\" returned undefined",
"locations": [
{
"line": 16,
"column": 4
}
],
"path": [
"updateUser",
"id"
]
}
]
}
The issue is clear, your resolver does not return an object containing id.
The docs say that Model.update returns an array in which the 2nd element is the affected row.
Hence, your resolver should look like:
async updateUser(obj, args) {
const resultArray = await User.update( ... )
return resultArray[1]
}
... To be replaced by whatever you need.
So apparently, update does NOT return affected rows for MSSQL, only the number of records affected.
This is true only for postgres when returning: true:
public static update(values: Object, options: Object): Promise<Array<affectedCount, affectedRows>>
Setting returning: true (for MSSQL) returns undefined (and order of params in the array is not even in the right order... i.e. first affectedRows -> undefined, then affectedCount ->num of affected rows.)
Tho get an object back you would need to do something like this:
Mutation: {
createUser: async (obj, args) =>
(await User.create(args.user)),
updateUser: async (obj, args, context, info) =>{
let user = args.user;
let response = await User.update(user,
{
where: {
[Op.or]: [{ email: user.email }, { id: user.id }, { username: user.username }, { lastname: user.lastname}]
},
//returning: true //not working... only for postgres db :(
}).then(ret => {
console.log('ret', ret);
return ret[0];
}).catch(error => {
console.log('error', error)
});
if (response > 0) return user; //return record
//return response > 0; //return true
}
}

Load form data via REST into vue-form-generator

I am building a form, that needs to get data dynamically via a JSON request that needs to be made while loading the form. I don't see a way to load this data. Anybody out here who can help?
JSON calls are being done via vue-resource, and the forms are being generated via vue-form-generator.
export default Vue.extend({
template,
data() {
return {
model: {
id: 1,
password: 'J0hnD03!x4',
skills: ['Javascript', 'VueJS'],
email: 'john.doe#gmail.com',
status: true
},
schema: {
fields: [
{
type: 'input',
inputType: 'text',
label: 'Website',
model: 'name',
maxlength: 50,
required: true,
placeholder: companyList
},
]
},
formOptions: {
validateAfterLoad: true,
validateAfterChanged: true
},
companies: []
};
},
created(){
this.fetchCompanyData();
},
methods: {
fetchCompanyData(){
this.$http.get('http://echo.jsontest.com/key/value/load/dynamicly').then((response) => {
console.log(response.data.company);
let companyList = response.data.company; // Use this var above
}, (response) => {
console.log(response);
});
}
}
});
You can just assign this.schema.fields.placeholder to the value returned by the API like following:
methods: {
fetchCompanyData(){
this.$http.get('http://echo.jsontest.com/key/value/load/dynamicly').then((response) => {
console.log(response.data.company);
this.schema.fields.placeholder = response.data.company
}, (response) => {
console.log(response);
});
}
}