I want to save all data by using react.js and Java Spring. I sent data with REST, but one of data class comes null to collections in MongoDB. I controlled whether or not all data types are equal. I cannot see and solve my errors. I share both Spring data type definitions and react.js definitions.
BildirimGrubu comes null
Java Spring:
package tr.com.innova.watcher;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import java.util.List;
/**
* Created by SBK on 03.09.2016.
*/
#Data
#JsonInclude(JsonInclude.Include.NON_NULL)
public class BildirimGrubu {
String emailMetni;
String smsMetni;
List<Alici> alici;
enum EmailEkTipi{
HICBIRI, EXCEL, PDF
};
EmailEkTipi ekTip;
enum BildirimYontemi{
EMAIL, SMS, HEPSI, HICBIRI
};
BildirimYontemi bildirimYont;
int mesajSayisi;
int mesajKarakter;
}
React.js:
import * as React from "react";
export enum EmailEkTipi{
HICBIRI, EXCEL, PDF
}
export enum BildirimYontemi {
EMAIL, SMS, HEPSI, HICBIRI
}
export enum TetikleyiciTipi{
CRON, SIMPLE
}
export class Alici {
label:string;
value:string;
constructor(name:string,
val:string) {
this.label = name;
this.value = val;
}
}
export class BildirimGrubu {
emailMetni:string;
smsMetni:string;
alici:Array<Alici>;
ekTip:EmailEkTipi;
bildirimYont:BildirimYontemi;
mesajSayisi:number;
mesajKarakter:number;
constructor(emailMetni:string, smsMetni:string, alici:Array<Alici>, ekTip:EmailEkTipi, bildirimYont:BildirimYontemi, mesajSayisi:number,mesajKarakter:number) {
this.emailMetni = emailMetni;
this.smsMetni = smsMetni;
this.alici = alici;
this.ekTip = ekTip;
this.bildirimYont = bildirimYont;
this.mesajSayisi = mesajSayisi;
this.mesajKarakter = mesajKarakter;
}
}
export class Tetikleyici {
tetikleyiciAdi:string;
aciklama:string;
tetikleyiciIcerik:TetikleyiciTipi;
durum:boolean;
bildirimGrubu:BildirimGrubu;
tip:TetikleyiciTipi;
bildirimEkle:boolean;
constructor(tetikleyiciAdi:string, aciklama:string, tetikleyiciIcerik:TetikleyiciTipi, durum:boolean, bildirimGrubu:BildirimGrubu, tip:TetikleyiciTipi, bildirimEkle:boolean) {
this.tetikleyiciAdi = tetikleyiciAdi;
this.aciklama = aciklama;
this.tetikleyiciIcerik = tetikleyiciIcerik;
this.durum = durum;
this.bildirimGrubu = bildirimGrubu;
this.tip = tip;
this.bildirimEkle = bildirimEkle;
}
}
export class Sorgu {
_id:string;
userName:string;
anaSorgu:string;
aciklama:string;
altSorguList:Array<string>;
tetikleyici:Tetikleyici;
sName:string;
constructor(id:string, username:string, anaSorgu:string, aciklama:string, altSorguList:Array<string>, tetikleyici:Tetikleyici, sName:string) {
this._id = id;
this.userName = username;
this.anaSorgu = anaSorgu;
this.aciklama = aciklama;
this.altSorguList = altSorguList;
this.tetikleyici = tetikleyici;
this.sName=sName;
}
}
Data to send DB with REST:
[new Sorgu("1","Hi","select","select sorgusu",["hi","hoy"],new Tetikleyici("tetikle", "hello", TetikleyiciTipi.CRON, true, new BildirimGrubu("a", "a", [["ali","bak"]], EmailEkTipi.EXCEL, BildirimYontemi.HEPSI, 1, 1), TetikleyiciTipi.CRON, true),"sorgu_8")]
I hope to transferred you my problems. Thank you for helps.
While again created classes, I realized that I forgot to add public. Therefore, java cannot access the objects of the class. Don't forget public. :)
Even so, thank you!
Related
I have a circular reference issue using this pattern approach. TypeError: Class extends value undefined is not a constructor or null .
The strange thing is, if I move the field.type.ts in src/constants.ts, it doesn't throw an error and it works as expected, but crashes on the Unit Tests. If it leave the fied.type.ts contents in it's own file, it crashes.
Maybe I am not using/understanding this dependency inversion pattern the right way. I could probably fixed by passing the FieldTypeToClassMapping as a parameter in Field.create(options: FieldOptions, fieldTypeMapping: FieldTypeToClassMapping), but I want to understand why this is happening.
import { StringField } from './string.field.model';
import { IntegerField } from './integer.field.model';
...
export const FieldTypeToClassMapping = {
//Constructor of eg. StringField class so I can use `new FieldTypeToClassMapping[options.type](options)`;
[FieldTypeEnum.STRING]: StringField,
[FieldTypeEnum.INTEGER]: IntegerField,
};
//field/field.ts
import { FieldOptions } from 'src/interfaces/field.options.interface';
import { FieldTypeToClassMapping } from 'src/model/template/field.type.to.mapping.ts'
export abstract class Field {
value: any;
type: string;
errors: string[] = [];
public constructor(options: FieldOptions) {
this.value = options.value;
this.type = options.type;
}
public static create(options: FieldOptions): any {
try {
return new FieldTypeToClassMapping[options.type](options);
} catch (e) {
throw new Error(`Invalid field type: ${options.type}`);
}
}
}
//field/integer.field.ts
import { FieldOptions } from 'src/interfaces/field.options.interface';
import { Field } from './field.model';
export class IntegerField extends Field {
constructor(options: FieldOptions) {
super(options);
}
protected validateValueDataType() {
this.validateDataType(this.value, "value");
}
protected validateDefaultDataType() {
this.validateDataType(this.defaultValue, "defaultValue");
}
}
//field/service.ts
payload const postFields = [
{
type: "string", //FieldTypeEnum.STRING,
value: 'a name'
},
];
const postFields = [
{
type: "string",
value: "John",
},
{
type: "integer",
value: 32,
},
];
const fieldsArray = [];
postFields.forEach((item) => {
const field: Field = Field.create(item);
fieldsArray.addField(field);
});
return fieldsArray;
The create(options: FieldOptions) function is defined inside the class Field, but then it tries to instantiate an instance of a class that extends Field.
I think that is where the problem arises. I don't know the entire contents of your files, but I imagine that at the top of any field.type.ts file you import Field. However since Field can instantiate any concrete implementation of itself it would need to know about them so you would need to import everything that extends Field inside Field.
I don't know/understand the dependency inversion pattern well enough to relate it to your question. But given the provided information, perhaps a Factory Pattern is what you need?
You could move the the function create(options: FieldOptions) to a FieldFactory class. Your create function is practically a factory function already.
I have the following lightning web component to read a JSON string and display them in Contact record Details page. Please note that I am new to lighting web components and making a considerable amount of effort to learn.
MyComponent.html
<template>
<lightning-record-form
object-api-name={contactObject}
fields={myFields}
onsuccess={handleContactCreated} onload={handleContactInitialized} >
</lightning-record-form>
</template>
MyComponent.js
import { LightningElement, wire, track } from 'lwc';
import findDetails from
'#salesforce/apex/JSONDemoController.getContactWithRelatedDataById';
import CONTACT_OBJECT from '#salesforce/schema/Contact';
import NAME_FIELD from '#salesforce/schema/Contact.Name';
import TEST_FIELD from '#salesforce/schema/Contact.TestField__c';
import SPOUSE_FIELD from '#salesforce/apex/ResponseJSONWrapper.spouse';
import ADDRESS_FIELD from
'#salesforce/apex/ResponseJSONWrapper.mailingAddress';
export default class ContactCreator extends LightningElement {
contactObject = CONTACT_OBJECT;
myFields = [SPOUSE_FIELD,ADDRESS_FIELD];
#track contacts;
#track error;
handleContactCreated(){
// Run code when account is created.
}
handleContactInitialized(){
findDetails()
.then(result => {
var responseObj = JSON.parse(result.getReturnValue());
this.SPOUSE_FIELD = responseObj.spouse;
this.ADDRESS_FIELD = responseObj.mailingAddress;
})
.catch(error => {
this.error = error;
});
myFields = [SPOUSE_FIELD,ADDRESS_FIELD];
}
}
JSONDemoController.cls
public class JSONDemoController {
#AuraEnabled
public static String getContactWithRelatedDataById() {
String response = '';
ResponseJSONWrapper wrapper = new ResponseJSONWrapper();
wrapper.spouse = 'Test Spouse';
wrapper.mailingAddress = 'Test Address';
response = JSON.serialize(wrapper);
return response;
}
}
ResponseJSONWrapper.cls
public with sharing class ResponseJSONWrapper {
public String spouse;
public String contactRecordType;
public Date birthDate;
public String mobile;
public String mailingAddress;
public String otherAddress;
public String languages;
public String level;
public String Description;
}
But I don't get the values I have hard coded in the lightning component when it is rendered. Nothing is there it's empty.
Can someone help to point out where I am going wrong ?
Change this line:
var responseObj = JSON.parse(result.getReturnValue());
To:
var responseObj = JSON.parse(result);
getReturnValue() is for Aura components.
You don't actually need to serialize the wrapper in apex and then parse in the component explicitly, the framework does the job by itself!
public class JSONDemoController {
#AuraEnabled //change return type to ResponseJSONWrapper
public static ResponseJSONWrapper getContactWithRelatedDataById() {
String response = '';
ResponseJSONWrapper wrapper = new ResponseJSONWrapper();
wrapper.spouse = 'Test Spouse';
wrapper.mailingAddress = 'Test Address';
return wrapper; //return the wrapper itself
}
and in .js file
findDetails()
.then(result => {
var responseObj = result;
...
})
This way the code will be less cluttered with not-needed code :)
I have a problem that I can't resolve.
Let's say we have some classes in a directory named services.
Each of theses classes contain a contructor() and send() method.
We can have differents classes such as Discord, Slack, SMS, etc.
Their goal is just to sent notification through external service.
I think I have to use an interface or an abstract class which contain contructor() and send() method but how can I instanciate every class and call send() in an elegantly way ?
My project structure :
services/
-> discord.js
-> slack.js
-> [...]
index.js
Regards.
I think what you are looking for is a kind of manager where you have a single send() function that chooses a specific service based on a parameter. Something like this:
services/index.js
import SlackService from 'slack.js';
import DiscordService from 'discord.js';
export const TYPES = {
SLACK: 'slack',
DISCORD: 'discord',
};
export class ServiceManager {
services;
constructor() {
this.services = {
[TYPES.DISCORD]: new DiscordService(/* discordConfig */),
[TYPES.SLACK]: new SlackService(/* slackConfig */),
};
}
send(type, data) {
return this.services[type].send(data);
}
}
index.js
import ServiceManager from 'services/index.js';
const serviceManager = new ServiceManager();
serviceManager.send(ServiceManager.TYPES.SLACK, { message: 'Sent to Slack' });
serviceManager.send(ServiceManager.TYPES.DISCORD, { message: 'Sent to Discord' });
Dynamically loading services from files
You can use require-dir to import all files from a directory and then map over those to create each service. The individual service files have to be written in a defined syntax for the manager to use them. Something like this:
services/slack.js (as example for all service files):
export const name = 'slack';
export class Service {
constructor() {
// Set up connection to slack
}
send() {
// Send something to slack
}
}
services/index.js
const requireDir = require('require-dir');
export class ServiceManager {
services;
constructor() {
const serviceObjects = requireDir('.');
this.services = Object.values(serviceObjects).reduce(
(services, { name, Service }) => {
services[name] = new Service();
return services;
}
)
}
getRegisteredServices() {
return Object.keys(this.services);
}
send(name, data) {
return this.services[name].send(data);
}
sendAll(data) {
Object.values(this.services).each(service => service.send(data));
}
}
index.js (stays pretty much the same)
import ServiceManager from 'ServiceManager.js';
const serviceManager = new ServiceManager();
console.log('Registered services are: ', serviceManager.getRegisteredServices());
serviceManager.send('slack', { message: 'Sent to Slack' });
serviceManager.send('discord', { message: 'Sent to Discord' });
I have a very strange problem. In angular (app built with ionic v1) I call some REST call built in java, but something goes wrong and chrome advise me with this error:
The code interesting is this, a REST service in angular js:
bankaccountsbyuser: function(_getbauser, _error){
var currentToken = _GetToken();
if(currentToken!=null){
var Headers = {
token: currentToken.tokenUser,
};
}
_timerTokenControl(currentToken, _error);
if (setupTime == null) {
console.log("token scaduto");
//modificare
//$window.location.href="login.html";
}
if (currentToken !== null) {
$http({
method : 'GET',
headers: Headers,
url : REST_URL+'bankaccount'
}).then(function successCallback(response) {
console.log(response)
_getbauser(response)
}, function errorCallback(response) {
console.log(response.statusText);
});
} else {
var alertPopup = $ionicPopup.alert({
title: 'Accesso negato!',
template: 'Devi essere un utente registrato, non sei loggato!'
});
console.log("NON SEI LOGGATO!!!");
}
},
debug:
How you can see, the get REST service returns an error, thus, let's see this REST service built in java:
package it.jack.fdd.services;
import java.util.List;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import it.jack.fdd.dao.FactoryDao;
import it.jack.fdd.dao.impl.BankAccountDaoImpl;
import it.jack.fdd.dao.interfaces.BankAccountDao;
import it.jack.fdd.domain.BankAccount;
import it.jack.fdd.domain.User;
import it.jack.fdd.dto.TokenUserDto;
import it.jack.fdd.dto.UserDto;
import it.jack.fdd.util.ConverterDTO;
#Path("/bankaccount")
public class BankAccountServices {
#GET
#Produces(MediaType.APPLICATION_JSON)
public List<BankAccount> getBankAccountOfUser() {
BankAccountDao baDao = new BankAccountDaoImpl();
List<BankAccount> balist = baDao.getBAByUserId(1);
return balist;
}
I tryed to pass the number "1" in the method, just to simplify. The method is implemented below:
package it.jack.fdd.dao.impl;
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import it.jack.fdd.dao.interfaces.BankAccountDao;
import it.jack.fdd.domain.BankAccount;
import it.jack.fdd.domain.Staff;
import it.jack.fdd.domain.User;
import it.jack.fdd.util.HibernateUtilLezione;
public class BankAccountDaoImpl extends BaseDaoImpl<BankAccount> implements BankAccountDao{
public List<BankAccount> getBAByUserId(int id) {
try{
Session session = HibernateUtilLezione.openSession();
Transaction tx = session.beginTransaction();
#SuppressWarnings("unchecked")
List<BankAccount> accounts = session.createQuery("from BankAccount b "
+ "where b.user= "+id).list();
tx.commit();
session.close();
return accounts;
}
catch(HibernateException e){
e.printStackTrace();
return null;
}
}
}
As you can see, the method ask for an id, and I put id 1 just to check, because in the database there is a field with that id. Trying in java, it returns me a list
[it.jack.fdd.domain.BankAccount#4f8d86e4]
And I checked also that the list has dimension 1 (thus, only one record, like in the database, only 1 record with that iduser)
Thus, trying to open this REST call using postman, the result is this:
The strange thing is that postman show me the same result to another REST call, that it worked before. But for this last REST call is not a problem, because strangely it works on my application, it doesn't work only in postman.
Thus, trying with Advanced REST Client I have a strange different result:
A strange, very big list that repeat every time the same field!! It is like a loop!
What happens? How I can solve?
Solved. The problem was in java's domain classes: when a domain class has a one-to-many relationship it's mandatory to put the tag #JsonIgnore to avoid these recurrent records in json file
Entity class:
package it.jack.fdd.domain;
// Generated 30-nov-2016 0.17.09 by Hibernate Tools 4.3.1.Final
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
/**
* BankAccount generated by hbm2java
*/
#Entity
#Table(name = "bank_account", catalog = "fdd_dbproducts")
public class BankAccount implements java.io.Serializable {
private Integer idbankAccount;
private User user;
private String iban;
private String pin;
private String society;
private Date expiration;
public BankAccount() {
}
public BankAccount(User user, String iban, String pin, String society) {
this.user = user;
this.iban = iban;
this.pin = pin;
this.society = society;
}
public BankAccount(User user, String iban, String pin, String society, Date expiration) {
this.user = user;
this.iban = iban;
this.pin = pin;
this.society = society;
this.expiration = expiration;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "idbank_account", unique = true, nullable = false)
public Integer getIdbankAccount() {
return this.idbankAccount;
}
public void setIdbankAccount(Integer idbankAccount) {
this.idbankAccount = idbankAccount;
}
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "fkuser_baccount", nullable = false)
public User getUser() {
return this.user;
}
public void setUser(User user) {
this.user = user;
}
#Column(name = "iban", nullable = false, length = 45)
public String getIban() {
return this.iban;
}
public void setIban(String iban) {
this.iban = iban;
}
#Column(name = "pin", nullable = false, length = 45)
public String getPin() {
return this.pin;
}
public void setPin(String pin) {
this.pin = pin;
}
#Column(name = "society", nullable = false, length = 45)
public String getSociety() {
return this.society;
}
public void setSociety(String society) {
this.society = society;
}
#Temporal(TemporalType.DATE)
#Column(name = "expiration", length = 10)
public Date getExpiration() {
return this.expiration;
}
public void setExpiration(Date expiration) {
this.expiration = expiration;
}
}
With the first router v.3 versions, I was doing that somewhere in my code :
let lastColors: Colors;
let node = this.router.routerState._root;
do {
if(node.value.component.hasOwnProperty('__colors')) {
lastColors = (<any>node.value.component).__colors;
}
} while(node = node.children[0]);
However, the _root: TreeNode<ActivatedRoute> property of RouterState is now private in alpha 8, breaking my code. It seems that now, RouterState isn't exposing the root TreeNode anymore. What's the proper way to explore the components tree now?
Have you tried this.router.routerState.root
export class RouterState extends Tree<ActivatedRoute> {
/**
* #internal
*/
constructor(
root: TreeNode<ActivatedRoute>, public queryParams: Observable<Params>,
public fragment: Observable<string>, public snapshot: RouterStateSnapshot) {
super(root);
}
toString(): string { return this.snapshot.toString(); }
}
Well in fact that was simple, I didn't read the router's .d.ts files with enough attention:
let lastColors: Colors;
let state = this.router.routerState.snapshot;
let route = state.root;
do {
// do something with route.component
} while(route = state.children(route)[0]);
Update: #angular/router is now stable and the API changed, again. Here is the new version :
let state = this.router.routerState.snapshot;
let route = state.root;
do {
// do something with route.component
} while(route = route.children[0]);