ButterCMS / java-starter-buttercms

Drop-in proof-of-concept Java + Spring app, fully integrated with your ButterCMS account
https://java-starter-buttercms.herokuapp.com/
0 stars 5 forks source link

Landing-page url route is hard-coded, vs passing slug #3

Closed ViolanteCodes closed 2 years ago

ViolanteCodes commented 2 years ago

The backup url route, \landing-page\<slug>\, should pass forward the slug to the API, so that the correct landing page is fetched, versus being hard-coded to landing-page-with-components. This allows the end user to set up alternate landing pages of the Landing Page Page Type and test them. One is already set with the slug alternate-landing-page in our test account.

I believe (I don't do Java) this means that in PageCollectionService.java, lines 30 and 31 (for the public LandingPageDto getLandingPage() function), in the Fields method, the call should be something like butterCMSClient.getPage("landing-page", Slug), instead of "*", "landing-page-with-components", i.e., page type should be passed as landing-page instead of "*" for all pages, and slug should be passed from url route instead of hard-coding in landing-page-with-components.

index url (/) is set correctly, :smile: (as in, set to landing-page-with-components page of landing-page Page Type.)

HonzaStefanik commented 2 years ago

I changed it to accept the slug and page type and pass it to the ButterCMS SDK. It defaults to landing-page-with-components.

However, I'm not sure if a given structure can be expected from landing-pages (eg the default landing-page-with-components vs some alternate-landing-page). Parsing JSON in Java can be a bit more annoying than for example in JS. A class representing each object has to be created in order to parse them. So if the structure doesn't match the landing-page-with-components one, it won't work.

If the structure stays same, it should work as it is right now in the fix of the first review. Otherwise, I will have to think about it a bit and refactor it to comply with this requirement.

ViolanteCodes commented 2 years ago

@HonzaStefanik The component types themselves are consistent, even if their order on the page changes, so what our other developers have done is create a data model for each of the component types, and then run an for loop inside the landing-page data model that matches a component type to the data type, e.g., if component=hero, then blah, if component = two_column_with_image, then blah.

Is there a reason that wouldn't work for Java? It's worked for all the other frameworks thus far.

HonzaStefanik commented 2 years ago

I think it should work if the structure is consistent (the order doesn't matter, it will adjust correctly). I'm not really sure how the exact use case should work, so you can try it and if it doesn't work, I'll discuss it with Prokop in person to get a better understanding what needs to be done.

ViolanteCodes commented 2 years ago

@HonzaStefanik I'm not entirely sure what you mean but we have an alternate landing page set up (Page Type "landing page", slug = "alternate-landing-page")

trying to access this url via /landing-page/alternate-landing-page/ results in a 500 error with the following error in terminal

2022-06-07 10:38:11.562 ERROR 31299 --- [nio-8080-exec-4] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is com.buttercms.exception.ButterCMSResponseException: Unexpected response deserialization error] with root cause

com.buttercms.exception.ButterCMSResponseException: Unexpected response deserialization error
        at com.buttercms.ButterCMSClient.readGenericRequest(ButterCMSClient.java:219) ~[buttercmsclient-1.10.jar:na]
        at com.buttercms.ButterCMSClient.getPage(ButterCMSClient.java:106) ~[buttercmsclient-1.10.jar:na]
        at com.buttercms.springstarterbuttercms.service.PageCollectionService.getLandingPage(PageCollectionService.java:32) ~[classes/:na]
        at com.buttercms.springstarterbuttercms.controller.IndexController.index(IndexController.java:25) ~[classes/:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
        at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-5.3.16.jar:5.3.16]
        at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) ~[spring-web-5.3.16.jar:5.3.16]
        at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) ~[spring-webmvc-5.3.16.jar:5.3.16]
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.3.16.jar:5.3.16]
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.16.jar:5.3.16]
        at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.16.jar:5.3.16]
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067) ~[spring-webmvc-5.3.16.jar:5.3.16]
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) ~[spring-webmvc-5.3.16.jar:5.3.16]
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.16.jar:5.3.16]
        at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.16.jar:5.3.16]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:655) ~[tomcat-embed-core-9.0.58.jar:4.0.FR]
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.16.jar:5.3.16]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:764) ~[tomcat-embed-core-9.0.58.jar:4.0.FR]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.58.jar:9.0.58]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
        at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.16.jar:5.3.16]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.16.jar:5.3.16]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
        at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.16.jar:5.3.16]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.16.jar:5.3.16]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.16.jar:5.3.16]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.16.jar:5.3.16]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:359) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:889) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1735) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
        at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
        at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
        at java.base/java.lang.Thread.run(Thread.java:829) ~[na:na]

We are very motivated to have this work correctly (e.g., movable components) as the "component-ability" of the data is a major selling point for our clients. A developer should be able to set up the template and schema for a page type, and then marketing, etc., should be able to create new landing pages that display properly in app, as long as they are using the components included with the landing page type.

HonzaStefanik commented 2 years ago

I will discuss it with Prokop then

ViolanteCodes commented 2 years ago

@HonzaStefanik Okay! Just keep me posted :smile: