See the documentation.
cuba-platform / restapi Goto Github PK
View Code? Open in Web Editor NEWCUBA REST API Add-on
License: Apache License 2.0
CUBA REST API Add-on
License: Apache License 2.0
See the documentation.
Currently in entities load/search methods it's possible to specify the only attribute for sorting.
@haulmont-git commented on Wed Dec 13 2017
Exposing services in REST have many limitations such as:
According to feedback, developers usually end up with creating custom Spring REST Controllers:
https://www.cuba-platform.com/discuss/t/there-is-a-way-to-generate-html-from-a-rest-api-call/3185/2
https://www.cuba-platform.com/discuss/t/how-to-restrict-rest-api-v2-to-allow-post-only/3166
So instead of reinventing spring-mvc within our REST services maybe we need to enhance custom controllers usage, here are some ideas on it:
Original issue: https://youtrack.haulmont.com/issue/PL-10144
When a new REST API token is stored, it is distributed among all nodes of the cluster. Right now, it is done asynchronously. This may cause the problem: in the cluster under a high load the token may be obtained, passed to another node, but the token was not replicated to the second node yet. Probably we should introduce a synchronous way of doing this (like is done for user sessions cuba.syncNewUserSessionReplication
).
In addition to using clusterManagerAPI.send(new TokenStoreAddAccessTokenMsg(....
we may optionally use the clusterManagerAPI.sendSync(new TokenStoreAddAccessTokenMsg(
in the ServerTokenStoreImpl.
There may be an application property cuba.syncTokenReplication
. The default value is false
. In the ServerTokenStoreImpl
all invocations of clusterManagerAPI.send
must be replaced with sendAsync
if the app property is set to true. See UserSessions.add(UserSession session)
method as an example.
The config cuba.rest.syncTokenReplication
is added, the default value is false
.
If true
, tokens will be sent to the cluster in a synchronous way.
In the platform updated jMockit
.
It is necessary to add an argument to run the tests correctly.
test {
jvmArgs "-javaagent:${classpath.find { it.name.contains("jmockit") }.absolutePath}"
}
Related: cuba-platform/cuba#2151
AR:
Platform 7.1.0 - Add-on 0.1-SNAPSHOT
ER:
For example:
Platform 7.1-SNAPSHOT - Add-on 7.1-SNAPSHOT
Platform 7.1.0 - Add-on 7.1.0 (or 7.1.1, 7.1.2, etc)
Platform 7.2.3 - Add-on 7.2.2
Run application on 7.1-SNAPSHOT with REST-API.
2019-04-19 11:27:38.381 ERROR [main] com.haulmont.cuba.core.sys.persistence.EclipseLinkSessionEventListener -
=================================================================
Problems with entity enhancement detected:
Entity class RefreshToken is missing some of enhancing interfaces: CubaEnhanced; PersistenceObject; PersistenceWeaved; PersistenceWeavedFetchGroups; PersistenceWeavedChangeTracking;
Entity class AccessToken is missing some of enhancing interfaces: CubaEnhanced; PersistenceObject; PersistenceWeaved; PersistenceWeavedFetchGroups; PersistenceWeavedChangeTracking;
Also, there is no entitiesEnhancing in build.gradle of the addon: https://github.com/cuba-platform/restapi/blob/master/build.gradle#L128
Publish rest-api-swagger.yaml
See:
Publish Swagger UI yaml
TC configurationWe have to publish schemes located in directory:
modules/rest-api/src/com/haulmont/addon/restapi/xsd/
Schemes should be published under http://schemas.haulmont.com/restapi/ path
Then update scheme usages in Wiki.
If the service method throws an exception, it is caught and new RestAPIException is thrown (ServicesControllerManager._invokeServiceMethod). That makes impossible to handle custom exception types.
Original issue: https://youtrack.haulmont.com/issue/PL-9864
Original issue: https://youtrack.haulmont.com/issue/PL-8538
By default, entity create and update operation must return a result that contains just the following fields:
{
"id": "<entityId>",
"_entityName": "<entityName>",
"_instanceName": "<intanceName>"
}
If other entity fields are required in the response, then an optional "responseView" query parameter must be passed in the request URL. In the case the creates/updated entity must be reloaded with this view and returned in the response JSON.
Added optional parameter "responseView" for create/update request. Now, by default, only 3 parameters are passed in the response.
{
"id": "<entityId>",
"_entityName": "<entityName>",
"_instanceName": "<intanceName>"
}
To disable this function, you must set the config cuba.rest.responseViewEnabled
to false
.
Method for loading entity views does not return info about built-in views (_minimal
, _base
, _local
). We can get built-in views separately using /metadata/entities/{entityName}/views/{viewName}
but it will require many separate requests e.g. if you want to build correct deep graph for some complex view.
So it makes sense to introduce includeSystem
flag which will return built-in views along with explicitly defined.
@haulmont-git commented on Thu Aug 03 2017
Typical usage: implement /recent query that returns 10 last orders / payments / etc
We want to set limit on server as business requirement
Original issue: https://youtrack.haulmont.com/issue/PL-9483
Sql-scripts restapi are not executed when restapi-addon is connected
app/rest/v2/oauth/revoke request with the wrong content type returns the Internal Server Error with 500 code
The following exception appears in tomcat.log
org.springframework.web.bind.MissingServletRequestParameterException: Required String parameter 'token' is not present
at org.springframework.web.method.annotation.RequestParamMethodArgumentResolver.handleMissingValue(RequestParamMethodArgumentResolver.java:195) ~[spring-web-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:104) ~[spring-web-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121) ~[spring-web-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:161) ~[spring-web-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128) ~[spring-web-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114) ~[spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) ~[spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) ~[spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963) ~[spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897) ~[spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) [spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) [spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:648) [servlet-api.jar:na]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) [spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) [servlet-api.jar:na]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230) [catalina.jar:8.5.9]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [catalina.jar:8.5.9]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat-websocket.jar:8.5.9]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) [catalina.jar:8.5.9]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [catalina.jar:8.5.9]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317) [spring-security-web-4.1.3.RELEASE.jar:4.1.3.RELEASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127) [spring-security-web-4.1.3.RELEASE.jar:4.1.3.RELEASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) [spring-security-web-4.1.3.RELEASE.jar:4.1.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.1.3.RELEASE.jar:4.1.3.RELEASE]
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:115) [spring-security-web-4.1.3.RELEASE.jar:4.1.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.1.3.RELEASE.jar:4.1.3.RELEASE]
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) [spring-security-web-4.1.3.RELEASE.jar:4.1.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.1.3.RELEASE.jar:4.1.3.RELEASE]
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:169) [spring-security-web-4.1.3.RELEASE.jar:4.1.3.RELEASE]```
---
Original issue: https://youtrack.haulmont.com/issue/PL-9936
Fix a problem with the migration of projects.
STR:
Disable read of some entity (i.e. sec$User)
Provide a method which loads these entities and expose it in REST API
@Override
public List<User> getUsers() {
LoadContext<User> lc = new LoadContext<>(User.class);
lc.setQueryString("select u from sec$User u");
return dataManager.loadList(lc);
}
[
{
"_entityName": "sec$User",
"_instanceName": "[]",
"id": "12000811-36f9-9055-42bb-d2546c46e32a"
}, {
"_entityName": "sec$User",
"_instanceName": "[]",
"id": "09f10596-832f-2873-0968-05892effd3e5"
}
]
Consider: not to strip attributes or do not return entities at all
Original issue: https://youtrack.haulmont.com/issue/PL-9272
http://localhost:8080/app/rest/v2/oauth/token
)01:42:12.406 INFO c.h.c.s.a.AuthenticationManagerBean - Logged in: 24668c0b-ce4d-a14c-da21-27ff4adb7735 [admin]
01:42:16.460 INFO c.h.c.s.a.AuthenticationManagerBean - Logged in: 78e5c771-47cf-bc42-2e69-9a35d391ed28 [admin]
01:42:17.419 INFO c.h.r.auth.ClientProxyTokenStore - REST API access token stored: [9265540714] ***-9c786317e72d
The error is probably caused by the issue cuba-platform/cuba#2045
Forum topic: https://www.cuba-platform.com/discuss/t/custom-portal-rest-api-failure-after-platform-upgrade/9571
A topic on support forum: link
In case of some REST service has few methods with the same name but with different parameters (overloaded methods) we cannot generate correct Swagger documentation due to restrictions in the Swagger 2.0 Specification (OAI/OpenAPI-Specification#182).
Will be fixed when swagger-core will be released with 2.0.0 version.
Support base64 encoded files in REST API file upload
Original issue: https://youtrack.haulmont.com/issue/PL-8458
ER:
Successful start
AR:
INFO: Server initialization in [564] milliseconds ╨░╨┐╤А 18, 2019 11:23:54 AM org.apache.catalina.core.StandardService startInternal INFO: Starting service [Catalina] ╨░╨┐╤А 18, 2019 11:23:54 AM org.apache.catalina.core.StandardEngine startInternal INFO: Starting Servlet engine: [Apache Tomcat/9.0.14] ╨░╨┐╤А 18, 2019 11:23:55 AM org.apache.catalina.startup.HostConfig deployWAR INFO: Deploying web application archive [C:\Projects\Addons\restapi\deploy\tomcat\webapps\restapi.war] 11:24:06.505 INFO c.h.cuba.core.sys.AppComponents - Using app components: [com.haulmont.cuba] 11:24:06.559 INFO c.h.c.c.s.AbstractWebAppContextLoader - Loading app properties from classpath:com/haulmont/addon/restapi/web-app.properties 11:24:06.567 INFO c.h.c.c.s.AbstractWebAppContextLoader - Loading app properties from /WEB-INF/local.app.properties 11:24:08.299 ERROR c.h.c.c.s.AbstractWebAppContextLoader - Error initializing application org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from class path resource [com/haulmont/cuba/web-spring.xml]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'cuba_DataManager' for bean class [com.haulmont.cuba.core.app.DataManagerBean] conflicts with existing, non-compatible bean definition of same name and class [com.haulmont.cuba.client.sys.DataManagerClientImpl] at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:419) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:336) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:304) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:188) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:224) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:195) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:257) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.context.support.AbstractXmlApplicationContext.loadBeanDefinitions(AbstractXmlApplicationContext.java:128) ~[spring-context-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.context.support.AbstractXmlApplicationContext.loadBeanDefinitions(AbstractXmlApplicationContext.java:94) ~[spring-context-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:133) ~[spring-context-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:636) ~[spring-context-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:521) ~[spring-context-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:144) ~[spring-context-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:95) ~[spring-context-5.1.6.RELEASE.jar:5.1.6.RELEASE] at com.haulmont.cuba.core.sys.CubaClassPathXmlApplicationContext.<init>(CubaClassPathXmlApplicationContext.java:27) ~[cuba-global-7.1-SNAPSHOT.jar:7.1-SNAPSHOT] at com.haulmont.cuba.core.sys.AbstractAppContextLoader.createApplicationContext(AbstractAppContextLoader.java:90) ~[cuba-global-7.1-SNAPSHOT.jar:7.1-SNAPSHOT] at com.haulmont.cuba.core.sys.AbstractAppContextLoader.initAppContext(AbstractAppContextLoader.java:62) ~[cuba-global-7.1-SNAPSHOT.jar:7.1-SNAPSHOT] at com.haulmont.cuba.core.sys.AbstractWebAppContextLoader.contextInitialized(AbstractWebAppContextLoader.java:78) ~[cuba-global-7.1-SNAPSHOT.jar:7.1-SNAPSHOT] at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4663) [catalina.jar:9.0.14] at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5131) [catalina.jar:9.0.14] at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) [catalina.jar:9.0.14] at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:713) [catalina.jar:9.0.14] at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:690) [catalina.jar:9.0.14] at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:695) [catalina.jar:9.0.14] at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:978) [catalina.jar:9.0.14] at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1850) [catalina.jar:9.0.14] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_181] at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_181] at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) [tomcat-util.jar:9.0.14] at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112) [na:1.8.0_181] at org.apache.catalina.startup.HostConfig.deployWARs(HostConfig.java:773) [catalina.jar:9.0.14] at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:427) [catalina.jar:9.0.14] at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1577) [catalina.jar:9.0.14] at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:309) [catalina.jar:9.0.14] at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:123) [catalina.jar:9.0.14] at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:424) [catalina.jar:9.0.14] at org.apache.catalina.util.LifecycleBase.setState(LifecycleBase.java:367) [catalina.jar:9.0.14] at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:934) [catalina.jar:9.0.14] at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:831) [catalina.jar:9.0.14] at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) [catalina.jar:9.0.14] at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1382) [catalina.jar:9.0.14] at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1372) [catalina.jar:9.0.14] at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_181] at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) [tomcat-util.jar:9.0.14] at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134) [na:1.8.0_181] at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:907) [catalina.jar:9.0.14] at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262) [catalina.jar:9.0.14] at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) [catalina.jar:9.0.14] at org.apache.catalina.core.StandardService.startInternal(StandardService.java:423) [catalina.jar:9.0.14] at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) [catalina.jar:9.0.14] at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:933) [catalina.jar:9.0.14] at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) [catalina.jar:9.0.14] at org.apache.catalina.startup.Catalina.start(Catalina.java:637) [catalina.jar:9.0.14] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_181] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_181] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_181] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_181] at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:350) [bootstrap.jar:9.0.14] at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:492) [bootstrap.jar:9.0.14] Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'cuba_DataManager' for bean class [com.haulmont.cuba.core.app.DataManagerBean] conflicts with existing, non-compatible bean definition of same name and class [com.haulmont.cuba.client.sys.DataManagerClientImpl] at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.checkCandidate(ClassPathBeanDefinitionScanner.java:348) ~[spring-context-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:286) ~[spring-context-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.context.annotation.ComponentScanBeanDefinitionParser.parse(ComponentScanBeanDefinitionParser.java:90) ~[spring-context-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.beans.factory.xml.NamespaceHandlerSupport.parse(NamespaceHandlerSupport.java:74) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1366) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1352) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:179) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:149) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:96) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionReader.java:513) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:393) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE] ... 58 common frames omitted ╨░╨┐╤А 18, 2019 11:24:08 AM org.apache.catalina.core.StandardContext startInternal SEVERE: One or more listeners failed to start. Full details will be found in the appropriate container log file ╨░╨┐╤А 18, 2019 11:24:08 AM org.apache.catalina.core.StandardContext startInternal SEVERE: Context [/restapi] startup failed due to previous errors ╨░╨┐╤А 18, 2019 11:24:08 AM org.apache.catalina.startup.HostConfig deployWAR INFO: Deployment of web application archive [C:\Projects\Addons\restapi\deploy\tomcat\webapps\restapi.war] has finished in [13┬а331] ms ╨░╨┐╤А 18, 2019 11:24:08 AM org.apache.coyote.AbstractProtocol start INFO: Starting ProtocolHandler ["http-nio-8080"] ╨░╨┐╤А 18, 2019 11:24:08 AM org.apache.coyote.AbstractProtocol start INFO: Starting ProtocolHandler ["ajp-nio-8009"] ╨░╨┐╤А 18, 2019 11:24:08 AM org.apache.catalina.startup.Catalina start INFO: Server startup in [13┬а419] milliseconds
FileUploadController may analyze not only the "name" request parameter but also the "id". If the id is passed then it should be set to the FileDescriptor object.
Forum topic: https://www.cuba-platform.ru/discuss/t/rest-zagruzka-fajla-s-predopredelennym-id/3011
Since id of such entities is passed as object it's not possible to call some methods where id is used in path fragment
DELETE /entities/{entityName}/{entityId}
GET /entities/{entityName}/{entityId}
PUT /entities/{entityName}/{entityId}
Solution:
Represent composite key identifier as JSON string and apply base64 URL encoding.
Model:
@Entity(name = "ref$CompositeKeyEntity")
@Table(name = "REF_COMPOSITE_KEY")
public class CompositeKeyEntity extends BaseGenericIdEntity<EntityKey> {
private static final long serialVersionUID = -2538345720324624741L;
@EmbeddedId
private EntityKey id;
@Column(name = "NAME")
private String name;
}
@Embeddable
@MetaClass(name = "ref$EntityKey")
public class EntityKey extends EmbeddableEntity {
@Column(name = "TENANT")
private Integer tenant;
@Column(name = "ENTITY_ID")
private Long entityId;
}
Encoding sample:
{tenant : 1, entityId: 1}
e3RlbmFudCA6IDEsIGVudGl0eUlkOiAxfQ==
/entities/ref$CompositeKeyEntity/e3RlbmFudCA6IDEsIGVudGl0eUlkOiAxfQ==
Original issue: https://youtrack.haulmont.com/issue/PL-9444
@haulmont-git commented on Tue Sep 12 2017
At the moment the only way to do it is to override the whole datatypes.xml file.
OR
Probably it will be enough just to have timezone information in he default datetime format.
Original issue: https://youtrack.haulmont.com/issue/PL-9674
It's not possible to setup REST API permissions from Generic UI.
STR:
AR:
REST API permissions are not present.
ER:
Use REST API permission should be available
The issue is a copy of cuba-platform/cuba#2045
There must be a setting that disables file uploading with the REST API. For example, it may be a specific permission with a name like cuba.restApi.fileUpload.enabled
.
Forum topic: https://www.cuba-platform.ru/discuss/t/zakryt-dostup-k-zagruzke-fajlov/3049
We have specific role permission "Use REST API" but it enables or disables REST fully
Original issue: https://youtrack.haulmont.com/issue/PL-10490
Update all dependencies in the gradle.build file using bom file.
Дать возможность послать вместе с графом сущностей соответствующие файлы для FileDescriptor.
Фронтенд разработчикам очень неудобно писать код разбивая загрузку файла в систему и коммит сущностей. Должна быть возможность послать всё вместе в один запрос.
Поддержать такое поведение для сервисов, чтобы можно было залить файл одновременно с вызовом метода сервиса. Думаю потребуется завести какой-то промежуточный тип для принимаемых файлов, которые ещё не в хранилище
Original issue: https://youtrack.haulmont.com/issue/PL-7720
Currently it's possible to obtain search result count by using returnCount
parameter. However there are some cases when only count is needed.
Added a new endpoint /entities/{entityName}/search/count
for GET and POST methods.
Provide an ability to commit several entities (of the same type) with a single request
Added the ability to create multiple entities, one request.
POST : http://localhost:8080/app/rest/v2/entities/sec$Group
Request body:
[
{
"name":"Group1"
},
{
"name":"Group2"
},
{
"name":"Group3"
}
]
Introduce isNull
entity search condition for Rest API Add-on.
Created a platform-independent enum RestFilterOp
for the Rest API Add-on and added a new condition isNull
.
Example:
"filter": {
"conditions": [
{
"property": "name",
"operator": "isNull"
}
]
}
}
WebSocket & PUSH support for REST-API controllers
Original issue: https://youtrack.haulmont.com/issue/PL-8921
In particular we need to prevent user passwords from being sent through REST API
Original issue: https://youtrack.haulmont.com/issue/PL-10186
Ability to upload temporary file for processing in a service using REST-API
Original issue: https://youtrack.haulmont.com/issue/PL-7330
If the middleware service is invoked with the standard rest api and the Accept-Language
header is set in the request, then it is expected that UserSession in the service implementation will have the corresponding locale. However, it doesn't.
The problem is that REST API filter sets the locale from the Accept-Language
header to the UserInvocationContext:
UserInvocationContext.setRequestScopeInfo(sessionId, locale, null, null, null);
When the middleware service is invoked after that, this value is not used.
Cannot set null value to dynamic attribute with the REST API
Original issue: https://youtrack.haulmont.com/issue/PL-10626
Related to:
See a case in related issue
For example:
Notice how one of the nested books holds title but the other, which is the same book as the parent of author, does not.
[ // books
{
"id": "123",
"_entityName": "book",
"title": "Book cuba-platform/cuba#123",
"author": {
"id": "234",
"_entityName": "author",
"name": "James Person",
"books": [
{ // note that this does not include "title"
"id": "123",
"_entityName": "book"
},
{ // but this does
"id": "456",
"_entityName": "book",
"title": "Book cuba-platform/cuba#456"
}
]
}
}
]
Original issue: https://youtrack.haulmont.com/issue/PL-10398
Motivation:
Added ability to pass enum data type to query parameters.
Query:
<query name="getDriversByStatus" entity="ref$Driver" view="_local">
<jpql><![CDATA[select u from ref$Driver u where u.status = :status]]></jpql>
<params>
<param name="status" type="com.haulmont.rest.demo.core.entity.DriverStatus"/>
</params>
</query>
GET-request:
http://localhost:8080/app/rest/v2/queries/ref$Driver/getDriversByStatus?status=ACTIVE
Headers:
Authorization: Bearer <access_token>
Content-Type: application/json
Original issue: https://youtrack.haulmont.com/issue/PL-8752
Currently, it is not possible to describe the graph of data to be fetched via rest API on the fly (using not predefined views on the server side). To make it possible developers could define them in the body of a get request, similarly to how it is achieved with GraphQL.
To prevent DDos, ability to use such functionality should be restrictable on the role level.
Original issue: https://youtrack.haulmont.com/issue/PL-9991
If the param value is null the corresponding condition should be removed from the result query
Original issue: https://youtrack.haulmont.com/issue/PL-9587
When we try to update a read-only attribute the 200 (OK) status is returned, although the attribute is not actually updated. Probably we should return an error in this case.
Original issue: https://youtrack.haulmont.com/issue/PL-9968
JSON in responses for entity create and update operations should not contain not-persistent attributes. Requests for entity read should return not-persistent attributes.
This should be done because of the following case.
There are a Debtor
and a Case
entities. The Case
entity has a not-persistent property that relates to debtor property:
@Table(name = "DEBT_CASE")
@Entity(name = "debt$Case")
public class Case extends StandardEntity {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "DEBTOR_ID")
protected Debtor debtor;
@MetaProperty(related = "debtor")
public String getNonPersistentDebtorTitle() {
return debtor == null ? null : debtor.getTitle();
}
}
Suppose we create or update the Case. We accidentally passed the "nonPersistentDebtorTitle" in JSON as well. The JSON has a reference to the Debtor.
{
"number": "CASE-001",
"nonPersistentDebtorTitle": "someValue",
"debtor": {
"id": "60885987-1b61-4247-94c7-dff348347f93"
}
}
In this case, after the entity is commited by the DataManager, it is serialized using the EntitySerializationAPI. By default, non-persistent meta-properties are also serialized, so a property value is read during the serialization. But since the "debtor.title" property is not read, an UnfetchedAttributeException is thrown.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.