There was a little bug in posts where any unsaved fields would be lost when removing a tag from the tag list. This happened because each tag element had <f:ajax render="@form" /> set.
Setting the JSF <f:ajax render="tags-output" /> had not facilitated the repainting of the tag list. This was a problem and I thought <f:ajax render="@form" /> was the solution.
Armed with new knowledge about JSF I have prefix the panelGroup's id with the form's id.
The general settings items are odd to model compared with the other entities that have been modeled within the blog platform. The other entities created for the blog platform, such as 'Post' entities, can have n many instances persisted. If modeled this same way all settings would become one entity. Would it be better in this instance to persist each setting item individually?
I decided to try out modeling each setting individually for now. Here is what I have implemented.
@Stateless
public class ConfigurationDAOBean {
@PersistenceContext
private EntityManager em;
public Configuration fetch(String item) {
List<Configuration> results = em.createQuery("SELECT c FROM Configuration c WHERE c.name = :name", Configuration.class)
.setParameter("name", item)
.getResultList();
if (results.isEmpty()) {
Configuration c = new Configuration();
c.setName(item);
em.persist(c);
return c;
}
return results.get(0);
}
public void store(Configuration c) {
em.merge(c);
}
}
Creating a basic implementation of the 'Pages' functionality gave me an idea for how to handle the dynamic URLs. First, URLs need a default suggestion. Second page authors need the option to create there own URL.
A page's URLs should default to the page's title. Spaces are replaced by hyphens. Diacritic marks will also need to be handled correctly. For now diacritic marks are on the backlog.
The URL property within the entity class is indirectly updated by changes to the title. The indirection allows for string replacement to happen. The string replacement ensure compliant URLs for each page.
When in freestyle mode fewer ajax requests are needed and therefore made by disabling/enabling the 'keyup' and 'blur' events respectively; as can be seen above.
As well as a default URL, it is nice to let authors create their own URL. Allowing a freestyle URL as well as a default URL involves a breakaway binding. This binding needs to be linked and unlinked at the author's will.
Using JSF's ui:fragment wrapper element is easy to display a 'No pages' message. This is what I have came up with:
PageDAOBean.java
[...]
public int countAllPages(){
Query q = em.createQuery("SELECT count(p) FROM Page p");
Number result = (Number) q.getSingleResult();
return result.intValue();
}
[...]
Pages.java (a JSF helper class)
[...]
public int countAll(){
return pb.countAllPages();
}
[...]
pages.xhtml (JSF)
[...]
<ui:fragment rendered="#{pages.countAll() == 0}" >
<h:outputText value="No pages yet. Why not add a page now?" />
</ui:fragment>
<ui:fragment rendered="#{pages.countAll() > 0}" >
Doing now :-)
</ui:fragment>
[...]
I have been using this pattern on each of the list pages. If you know of a better way, feel free to let me know.
Blogs normally have one or two pages. An example of what I mean by a page would be an 'about' page.
For now the blog platform's pages will include the following fields:
Title
Description
Body (i.e. the content of the page)
The view will be implemented on the front-end. The back-end will have the create, update, and delete functionality.
The URL pattern to retrieve a page in the front-end will be:
/<hyphenated page title>.html
I will use the page's title to query the database for the record. The .html URL ending will give the regex a solid stopping point. This will let the Java container 404 more invalid requests. Only the requests that match the pattern will hit the database. For the invalid requests that do hit the database something akin to this should do for raising a 404 page not found.
public void findPage(Long id) throws IOException {
page = ps.getPageById(id);
if (page == null) {
FacesContext.getCurrentInstance().getExternalContext().responseSendError(HttpServletResponse.SC_NOT_FOUND, "page not found");
FacesContext.getCurrentInstance().responseComplete();
}
}