Forming an ExecuteSearch Soap action for Filenet - filenet-p8

I wrote a nodeJs service and tried to use the strong-soap library to try to ExecuteSearch on IBM Filenet. This is function that I wrote with the arguments to try and execute the search:
filenetResponse = await client.FNCEWS35Service.FNCEWS35InlinePort.ExecuteSearch({
ExecuteSearchRequest: {
SelectionFilter: {
IncludeProperties: { $attributes: { maxRecursion: 1, maxSize: 1, maxElements: 1 }, $value: 'test' },
IncludeTypes: { $attributes: { maxRecursion: 1, maxSize: 1, maxElements: 1 }, $value: 'test' },
ExcludeProperties: 'test',
$attributes: {
maxRecursion: 1,
maxSize: 1,
maxElements: 1
}
},
$attributes: {
maxElements: 1,
continueFrom: 'test',
continuable: true
}
}
});
I'm getting the following error when I send it to Filenet:
"root": {
"Envelope": {
"Body": {
"Fault": {
"faultcode": "e:Server",
"faultstring": "class com.filenet.api.exception.EngineRuntimeException:Web services value for {http://www.w3.org/2001/XMLSchema-instance}type expected. Path when error was detected ExecuteSearchRequest.",
"detail": {
"ErrorStack": {
"ErrorName": "REQUIRED_VALUE_ABSENT",
"ErrorRecord": {
"Source": "com.filenet.api.exception.EngineRuntimeException",
"Description": "Web services value for {http://www.w3.org/2001/XMLSchema-instance}type expected. Path when error was detected ExecuteSearchRequest.",
"Diagnostic": [
{
"$attributes": {
"diagnosticType": "exceptionCode"
},
"$value": "TRANSPORT_WSI_VALUE_EXPECTED"
},
I've compared the argument that I am sending with the ExecuteSearch describe() but could not find what type am I missing that is causing the error.
I was thinking if it was the header, so I tried adding this too but it still gives me the same error:
client.addSoapHeader({ id: '', NoTxResume: '' }, 'TxId');
client.addSoapHeader({ Locale: 'en-us', Timezone: '' }, 'Localization');
I'm starting to wonder if I should keep trying or just discard this idea and move on to using Java as there are working examples that I can use.

Related

How can I get data inside parent component in strapi?

I have this single type in my strapi dashboard :
I Have a component called Logo
Another component called Links, it contains another component called Link
Finally a component called MenuButton.
When I go to http://localhost:1337/api/global?populate=* I got :
{
"data": {
"id": 1,
"attributes": {
"createdAt": "2021-12-27T11:54:36.177Z",
"updatedAt": "2021-12-27T11:54:54.737Z",
"publishedAt": "2021-12-27T11:54:54.731Z",
"logo": {
"id": 1,
"name": null
},
"navigation": {
"id": 1 // why I don't get links here ?
},
"menuButton": {
"id": 1,
"icon": ""
}
}
},
"meta": {
}
}
I Already published my content and allowed permissions for public.
My question is :
How can I access to the links inside navigation object ?
See my earlier answer here
Strapi 4 requires you to populate your request (see: population documentation )
which could look like this (for level 2 population):
// populate request
const qs = require('qs')
const query = qs.stringify(
{
populate: {
Product: {
populate: ['Image']
}
}
},
{
encodeValuesOnly: true
}
)
// get id
const id = yourId
// get rquest
const Response= await axios.get(
`http://localhost:1337/api/[your api]/${id }/?${query}`
)
Now media links should be included in your response
To retrieve up to 5 levels deep, you can install this package npm i strapi-plugin-populate-deep

How to handle graphql errors on Apollo server? [duplicate]

In an express-graphql app, I have a userLogin resolver like so:
const userLogin = async ({ id, password }), context, info) => {
if (!id) {
throw new Error('No id provided.')
}
if (!password) {
throw new Error('No password provided.')
}
// actual resolver logic here
// …
}
If the user doesn't provide an id AND a password, it will throw only one error.
{
"errors": [
{
"message": "No id provided.",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"userLogin"
]
}
],
"data": {
"userLogin": null
}
}
How is it possible to throw multiple errors in the errors response array?
There is no way to throw an array of errors in JavaScript or otherwise have a single resolver reject with more than one error. A GraphQL response includes an errors array and not just a single error object because the total response can include multiple errors when those errors originate from different fields. Consider this schema and resolvers:
type Query {
a: String
b: String
c: String
}
const resolvers = {
Query: {
a: () => { throw new Error('A rejected') },
b: () => { throw new Error('B rejected') },
c: () => 'Still works!',
},
}
If you query all three fields...
query {
a
b
c
}
Your data will look something like this:
{
"errors": [
{
"message": "A rejected",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"a"
]
},
{
"message": "B rejected",
"locations": [
{
"line": 3,
"column": 3
}
],
"path": [
"b"
]
}
],
"data": {
"a": null,
"b": null,
"c": "Still works!"
}
}
This is because GraphQL supports partial responses. However, keep in mind that this works because the fields are nullable. If they were non-null, those errors would bubble up to the closest nullable parent field.
Here are some alternative approaches:
You can utilize formatError to change how the errors returned by GraphQL are displayed to the client. That means you can include any sort of extra information with your errors, like an error code or multiple error messages. A simple example:
// The middleware
app.use('/graphql', graphqlExpress({
schema: schema,
formatError: (error) => ({
message: error.message,
path: error.path,
locations: error.locations,
errors: error.originalError.details
})
}))
// The error class
class CustomError extends Error {
constructor(detailsArray) {
this.message = String(details)
this.details = details
}
}
// The resolver
const userLogin = async ({ id, password }), context, info) => {
const errorDetails = []
if (!id) errorDetails.push('No id provided.')
if (!password) errorDetails.push('No password provided.')
if (errorDetails.length) throw new CustomError(errorDetails)
// actual resolver logic here
}
Your response then looks more like this:
{
"errors": [
{
"message": "[No id provided.,No password provided.]",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"userLogin"
]
"errors" [
"No id provided.",
"No password provided."
]
}
],
"data": {
"userLogin": null
}
}
That said, there's something a bit unsavory about returning user-facing error messages alongside GraphQL validation errors. Another approach that some APIs have taken is to include an errors field alongside the actual mutation response. For example:
type Mutation {
userLogin: UserLoginResponse
}
type UserLoginResponse {
response: User
errors: [String!]
}
You can also use unions to achieve a similar effect:
type Mutation {
userLogin: UserLoginResponse
}
type Errors {
errors: [String!]!
}
union UserLoginResponse = User | Errors

Is there way to redirect strapi error messages which I see in UI to the stdout?

I am using the Strapi v3.0.0-beta.18.7 UI and the error in the UI are shown partly so it is impossible to read the full text of the error message.
I suggest use a custom middleware to manage your needs.
Here is the documentation to create a middleware - https://strapi.io/documentation/3.0.0-beta.x/concepts/middlewares.html
Step 1: Create the middleware
Path — middlewares/log/index.js
module.exports = strapi => {
return {
initialize() {
strapi.app.use(async (ctx, next) => {
await next();
const status = ctx.status;
if (status < 200 || status >= 300) {
console.log(ctx.body);
}
});
},
};
};
Step 2: Enable the middleware
Path — config/environments/development/middleware.json
{
"log": {
"enabled": true
}
}
Step 3: Set the middleware in the right order
Path — config/middleware.json
{
"timeout": 100,
"load": {
"before": [
"log",
"responseTime",
"logger",
"cors",
"responses",
"gzip"
],
"order": [
"Define the middlewares' load order by putting their name in this array is the right order"
],
"after": [
"parser",
"router"
]
}
}

Partial Update Mutations(GraphQL)

How can I be able to update a node with only one field change and leave the rest of the fields alone?
My User Type
type User {
id: ID!
user_id: String!
username: String!
email: String!
role: Role!
isVerified: Boolean!
}
My Input Types
input UserUpdateInput {
user_id: String
username: String
email: String
password: String
role: Role
isVerified: Boolean
}
input UserWhereUniqueInput {
id: ID
user_id: String
email: String
}
My Mutation type
type Mutation {
updateUser(data: UserUpdateInput!, where: UserWhereUniqueInput): User
}
My Resolver
function updateUser(root, args, context, info){
return context.db.mutation.updateUser({
data: args.data,
where: {
id: args.where.id
}
}, info)
}
This is the request am sending on the GraphQL playground
mutation{
updateUser(
data: {
isVerified: true
}
where:{
user_id : "afc485b"
}
)
{
isVerified
}
}
This is the error am getting
{
"errors": [
{
"message": "Cannot read property 'mutation' of undefined",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"updateUser"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"stacktrace": [
"TypeError: Cannot read property 'mutation' of undefined"
Someone help me. What am I missing?
After updating my server as suggested by Daniel Rearden on the answer section, am getting a new error
{
"message": "Cannot read property 'updateUser' of undefined",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"updateUser"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"stacktrace": [
"TypeError: Cannot read property 'updateUser' of undefined"
The error is the result of not correctly adding the db property to you context. Assuming you're still using version 1, your code should look something like this:
const { prisma } = require('./generated/prisma-client')
const server = new ApolloServer({
...
context: {
db: prisma,
},
})
First thing I notice is you GQL query is not correct.
Yours:
mutation{
updateUser(
data: {
isVerified: true
}
where:{
user_id : "afc485b"
}
)
{
isVerified
}
}
after the word "mutation" you set a name to the call, i.e.
"UpdateUser" but can literally be anything. for each part of the
where clause you need to make the check value an object, i.e.
where: { myProperty: {eq: "some value"}}
So your query should be more like this:
mutation UpdateUser {
updateUser(
data: {isVerified: true}
where:{user_id : {eq: "afc485b"}}
)
{
isVerified
}
}
Hope that helps a little... I didn't fully read the rest but thought this would help with the initial error you were getting.

Parsing Mulitlevel Javascript Objects in Grails 2.1

I am trying to send data to my controller from an ajax function that needs to have multiple levels, so something like this:
{
"lob": {
"TESTING": [
{
"name": "color",
"value": "1"
},
{
"name": "time",
"value": "2"
},
{
"name": "jeremy",
"value": "3"
},
{
"name": "fourtytwo",
"value": "4"
},
{
"name": "owl",
"value": "5"
},
{
"name": "why",
"value": "6"
},
{
"name": "derp",
"value": "7"
},
{
"name": "where",
"value": "8"
}
]
}
}
but when it sends to grails I am getting this when I print out the params
[lob[TESTING][4][value]:5,
lob[TESTING][3][name]:fourtytwo,
lob[TESTING][6][name]:derp,
lob[TESTING][5][name]:why,
lob[TESTING][3][value]:4,
lob[TESTING][1][value]:2,
lob[TESTING][2][value]:3,
lob[TESTING][5][value]:6,
lob[TESTING][1][name]:time,
lob[TESTING][0][value]:1,
lob[TESTING][6][value]:7,
lob[TESTING][0][name]:color,
lob[TESTING][7][value]:8,
lob[TESTING][4][name]:owl,
lob[TESTING][7][name]:where,
lob[TESTING][2][name]:jeremy,
action:save,
controller:LOB]
The data I am sending from JavaScript:
{
lob: {
TESTING: $form.serializeArray()
}
}
I have been reading multiple forums saying using JSON.parse or request.JSON but these solutions do not seem to be fixing my problems. I want to be able to access the data like
params.lob.testing.each{ a->
println a
}
I will be doing alot more than just that but it would be nice to be able to access the data in that fashion. I am using Grails 2.1 and Jquery 1.7.2
Actually Grails makes it very easy. I've taken your test data and ran it through the following:
import grails.converters.JSON
class LobController {
def save = {
def json = request.JSON
json.lob.TESTING.each {item->
println "Name: ${item.name} - Value: ${item.value}"
}
//render something back if you need to here
}
}
And it outputs:
Name color - Value: 1
Name time - Value: 2
Name jeremy - Value: 3
Name fourtytwo - Value: 4
Name owl - Value: 5
Name why - Value: 6
Name derp - Value: 7
Name where - Value: 8
I created a UrlMapping entry like this (you probably already have this):
"/myApi"(controller: "lob", parseRequest: true) {
action = [POST: "save"]
}
The parseRequest: true will automatically parse the incoming JSON.
I found a `serializeJSON' function that might replace the serializeArray() to format this for JSON. The following was provided by Arjen Oosterkamp on the jQuery serializeArray page:
(function( $ ){
$.fn.serializeJSON=function() {
var json = {};
jQuery.map($(this).serializeArray(), function(n, i){
json[n['name']] = n['value'];
});
return json;
};
})( jQuery );
Simply use as $('form').serializeJSON();
All credit for that function goes to Arjen Oosterkamp...

Resources