What are the PdfPCellEvent equivalent in iText7? - itext7

I am trying to run some samples from whitepaper "digitalsignatures20130304 A White Paper by Bruno Lowagie" [page 54]. I could not find the iText7 equivalents for PdfPCellEvent, PdfContentByte.
Please guide me.

iText 7 is a not a clone of iText 5 with some refactored package or class names, it has a new architecture. Thus, there is not always a 1:1 corresponding class but there are other ways to achieve the same effect.
It helps to look at the ports of the samples by the iText people; on github you can find many samples from the whitepaper ported to iText 7 in the i7js-signatures project.
For example you mention page 54 of the Digital Signatures for PDF documents whitepaper. Considering the keywords you gave and the fact that there is but one example on that page, I assume you want to translate this method and helper class:
protected PdfPCell createSignatureFieldCell(PdfWriter writer, String name) {
PdfPCell cell = new PdfPCell();
cell.setMinimumHeight(50);
PdfFormField field = PdfFormField.createSignature(writer);
field.setFieldName(name);
field.setFlags(PdfAnnotation.FLAGS_PRINT);
cell.setCellEvent(new MySignatureFieldEvent(field));
return cell;
}
public class MySignatureFieldEvent implements PdfPCellEvent {
public PdfFormField field;
public MySignatureFieldEvent(PdfFormField field) {
this.field = field;
}
public void cellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) {
PdfWriter writer = canvases[0].getPdfWriter();
field.setPage();
field.setWidget(position, PdfAnnotation.HIGHLIGHT_INVERT);
writer.addAnnotation(field);
}
}
You find the port hereof in the class C2_11_SignatureWorkflow:
protected Cell createSignatureFieldCell(String name) {
Cell cell = new Cell();
cell.setHeight(50);
cell.setNextRenderer(new SignatureFieldCellRenderer(cell, name));
return cell;
}
class SignatureFieldCellRenderer extends CellRenderer {
public String name;
public SignatureFieldCellRenderer(Cell modelElement, String name) {
super(modelElement);
this.name = name;
}
#Override
public void draw(DrawContext drawContext) {
super.draw(drawContext);
PdfFormField field = PdfFormField.createSignature(drawContext.getDocument(), getOccupiedAreaBBox());
field.setFieldName(name);
field.getWidgets().get(0).setHighlightMode(PdfAnnotation.HIGHLIGHT_INVERT);
field.getWidgets().get(0).setFlags(PdfAnnotation.PRINT);
PdfAcroForm.getAcroForm(drawContext.getDocument(), true).addField(field);
}
}
As you can see there are certain differences, in particular instead of an event a Renderer is used, and the field construction and positioning aren't separated anymore, they take place at the same location in the code.

Related

How to use #ConfigProperties with a Converter class

I tried to implement a custom config type and it worked. However, when I use the custom type with a group of config using the #ConfigProperties it fails to automatically recognize the property by its name and instead treats the property as an object with a nested property.
How can I implement such a behavior correctly? (I am new to Quarkus, so please correct me if I am doing something wrong here)
Here is a code snippet that converts a custom type:
public class Percentage {
private double percentage;
public Percentage() {}
public Percentage(double percentage) {
this.percentage = percentage;
}
public void setPercentage(double percentage) {
this.percentage = percentage;
}
public double getPercentage() {
return this.percentage;
}
}
#Priority(300)
public class PercentageConverter implements Converter<Percentage> {
#Override
public Percentage convert(String value) {
int percentIndex = value.indexOf("%");
return new Percentage(Double.parseDouble(value.substring(0, percentIndex - 1)));
}
}
/// this works ------
public class Hello {
#ConfigProperty(name = "custom.vat")
Percentage vat;
public Hello () {
}
// .....
}
/// however, this fails
#ConfigProperties(prefix = "custom")
public class CustomConfig {
public Percentage vat;
public Percentage profit;
}
javax.enterprise.inject.spi.DeploymentException: No config value of type [double] exists for: custom.vat.percentage
at io.quarkus.arc.runtime.ConfigRecorder.validateConfigProperties(ConfigRecorder.java:39)
Unfortunately, I believe this does not work because Quarkus #ConfigProperties, handles these cases as if they were subgroups and try to map nested properties with the configuration (and not use the Converter).
Feel free to open up an issue in Quarkus GH if you feel this should change: https://github.com/quarkusio/quarkus/issues
Alternately, you can use SR Config #ConfigMapping: https://smallrye.io/docs/smallrye-config/mapping/mapping.html. It covers a few more cases, including direct Conversion and in the future it may replace Quarkus #ConfigProperties.

Customize Section title in Spring Auto Rest Docs

I want to customize Section "title" in auto-section.adoc[] file generated by Spring Auto Rest Docs. Spring Auto Rest Docs resolves section title using #title Javadoc tag on the method(if present) or from the method name (as mentioned in docs), but i can't inlcude #title in the Javadoc tag of method as the controller class is from other JAR, also I don't want the default generated method name. So, how to customize Section title in Spring Auto Rest Docs.
E.g. In auto generated auto-section.adoc[]
I don't want
=== Resolved Method Name
I want
=== Something else
Any help? Thanks.
Spring Auto REST Docs determines the title by looking at the #title tag and if this is not found, the method name is taken. There is currently no way to directly customize this behavior. If you can not modify the Javadoc, like in your case, you have to add the information via the snippet. There are at least two options:
Create a custom template. But then you are limited to the information available to the snippet and thus there are not a lot of alternatives to hard-coding text. See https://scacap.github.io/spring-auto-restdocs/#snippets-customization
Create a custom snippet. This gives you full control over everything and thus a snippet could be created that takes "Something else" as an input and uses it as the title. See https://scacap.github.io/spring-auto-restdocs/#snippets-custom to create custom snippets and https://scacap.github.io/spring-auto-restdocs/#snippets-section-custom-snippet to include custom snippets in the section snippet.
I achieved customizing section title in auto-section.adoc as below:
1) I created custom section snippet that extends SectionSnippet:
class CustomSectionSnippet extends SectionSnippet {
private final String title;
public CustomSectionSnippet(final Collection<String> sectionNames, final boolean skipEmpty,
final String title) {
super(sectionNames, skipEmpty);
this.title = title;
}
#Override
protected Map<String, Object> createModel(final Operation operation) {
final Map<String, Object> model = super.createModel(operation);
if (title != null) {
model.put("title", title);
}
return model;
}
}
2) And then the custom section builder that extends SectionBuilder:
class CustomSectionBuilder extends SectionBuilder {
private Collection<String> snippetNames = DEFAULT_SNIPPETS;
private final boolean skipEmpty = false;
private String title;
#Override
public CustomSectionBuilder snippetNames(final String... snippetNames) {
this.snippetNames = Arrays.asList(snippetNames);
return this;
}
public CustomSectionBuilder sectionTitle(final String title) {
this.title = title;
return this;
}
#Override
public SectionSnippet build() {
return new CustomSectionSnippet(snippetNames, skipEmpty, title);
}
}
3) And then used it like this:
#Test
void testApi() throws Exception {
final MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("name", "test");
this.mockMvc.perform(post("/api")
.params(params)
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andDo(commonDocumentation(
new CustomSectionBuilder()
.sectionTitle("Something else") // <-- custom section title
.snippetNames(
AUTO_AUTHORIZATION,
AUTO_REQUEST_FIELDS,
REQUEST_HEADERS,
REQUEST_PARAMETERS,
RESPONSE_FIELDS,
CURL_REQUEST,
HTTP_RESPONSE)
.build()
));
}
And now I'm able to pass Something else as a section title that will be included in the auto generated auto-section.adoc file.
Thanks #florian-benz for help :)

JavaFX - Get CheckBox properties from outside GUIController

In JavaFX I want to check if a checkbox is selected and I want to do this using the lookup(#id) method. However this method returns a Node, which doesn't have the isSelected() method.
The code below shows the GUIController and a class Visualize it calls, where the status of the checkbox is read. I added a solution (reading the checkbox properties in GUIController and passing them to Visualize), but this is not how I want to proceed. I whish that the checkbox status is read in Visualize, because there will be many other GUI elements that I need to read so it is more compact to pass on a single object to Visualize instead of a list precomputed in GUIController.
Thank you for suggestions!
GUI Controller:
public class GUIController implements Initializable {
#FXML private AnchorPane RootPane;
#FXML private CheckBox TextCheckBox;
#Override
public void initialize(URL url, ResourceBundle rb) {
Boolean TextCheckBoxSelected = TextCheckBox.isSelected();
Visualize visualizeInstance = new Visualize();
root3D = visualizeInstance.draw(RootPane, TextCheckBoxSelected);
/* ... */
Class called by GUIController:
public class Visualize {
public Visualize() {
//
}
public Group draw(AnchorPane RootPane, Boolean TextCheckBoxSelected) {
System.out.println(RootPane.lookup("#TextCheckBox"));
System.out.println(TextCheckBoxSelected);
/* ... */
Output:
CheckBox[id=TextCheckBox, styleClass=check-box]'Text'
true
If you really want to do it this way, just downcast the result of the lookup:
public class Visualize {
// ...
public Group draw(AnchorPane rootPane) {
CheckBox textCheckBox = (CheckBox) rootPane.lookup("#TextCheckBox");
boolean selected = textCheckBox.isSelected();
// ...
}
}
If you are doing this because you need your Visualize object to respond to changes in the CheckBox's selected state, then consider passing a BooleanProperty instead, which you can observe if you need:
public class Visualize {
private BooleanProperty selectedProperty ;
public Visualize(BooleanProperty selectedProperty) {
this.selectedProperty = selectedProperty ;
// ...
}
// ...
public Group draw() {
boolean selected = selectedProperty.get();
// ...
}
}
and
Visualize visualizeInstance = new Visualize(textCheckBox.selectedProperty());
root3D = visualizeInstance.draw();

How to correctly use PagedResourcesAssembler from Spring Data?

I'm using Spring 4.0.0.RELEASE, Spring Data Commons 1.7.0.M1, Spring Hateoas 0.8.0.RELEASE
My resource is a simple POJO:
public class UserResource extends ResourceSupport { ... }
My resource assembler converts User objects to UserResource objects:
#Component
public class UserResourceAssembler extends ResourceAssemblerSupport<User, UserResource> {
public UserResourceAssembler() {
super(UserController.class, UserResource.class);
}
#Override
public UserResource toResource(User entity) {
// map User to UserResource
}
}
Inside my UserController I want to retrieve Page<User> from my service and then convert it to PagedResources<UserResource> using PagedResourcesAssembler, like displayed here: https://stackoverflow.com/a/16794740/1321564
#RequestMapping(value="", method=RequestMethod.GET)
PagedResources<UserResource> get(#PageableDefault Pageable p, PagedResourcesAssembler assembler) {
Page<User> u = service.get(p)
return assembler.toResource(u);
}
This doesn't call UserResourceAssembler and simply the contents of User are returned instead of my custom UserResource.
Returning a single resource works:
#Autowired
UserResourceAssembler assembler;
#RequestMapping(value="{id}", method=RequestMethod.GET)
UserResource getById(#PathVariable ObjectId id) throws NotFoundException {
return assembler.toResource(service.getById(id));
}
The PagedResourcesAssembler wants some generic argument, but then I can't use T toResource(T), because I don't want to convert my Page<User> to PagedResources<User>, especially because User is a POJO and no Resource.
So the question is: How does it work?
EDIT:
My WebMvcConfigurationSupport:
#Configuration
#ComponentScan
#EnableHypermediaSupport
public class WebMvcConfig extends WebMvcConfigurationSupport {
#Override
protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(pageableResolver());
argumentResolvers.add(sortResolver());
argumentResolvers.add(pagedResourcesAssemblerArgumentResolver());
}
#Bean
public HateoasPageableHandlerMethodArgumentResolver pageableResolver() {
return new HateoasPageableHandlerMethodArgumentResolver(sortResolver());
}
#Bean
public HateoasSortHandlerMethodArgumentResolver sortResolver() {
return new HateoasSortHandlerMethodArgumentResolver();
}
#Bean
public PagedResourcesAssembler<?> pagedResourcesAssembler() {
return new PagedResourcesAssembler<Object>(pageableResolver(), null);
}
#Bean
public PagedResourcesAssemblerArgumentResolver pagedResourcesAssemblerArgumentResolver() {
return new PagedResourcesAssemblerArgumentResolver(pageableResolver(), null);
}
/* ... */
}
SOLUTION:
#Autowired
UserResourceAssembler assembler;
#RequestMapping(value="", method=RequestMethod.GET)
PagedResources<UserResource> get(#PageableDefault Pageable p, PagedResourcesAssembler pagedAssembler) {
Page<User> u = service.get(p)
return pagedAssembler.toResource(u, assembler);
}
You seem to have already found out about the proper way to use but I'd like to go into some of the details here a bit for others to find as well. I went into similar detail about PagedResourceAssembler in this answer.
Representation models
Spring HATEOAS ships with a variety of base classes for representation models that make it easy to create representations equipped with links. There are three types of classes provided out of the box:
Resource - an item resource. Effectively to wrap around some DTO or entity that captures a single item and enriches it with links.
Resources - a collection resource, that can be a collection of somethings but usually are a collection of Resource instances.
PagedResources - an extension of Resources that captures additional pagination information like the number of total pages etc.
All of these classes derive from ResourceSupport, which is a basic container for Link instances.
Resource assemblers
A ResourceAssembler is now the mitigating component to convert your domain objects or DTOs into such resource instances. The important part here is, that it turns one source object into one target object.
So the PagedResourcesAssembler will take a Spring Data Page instance and transform it into a PagedResources instance by evaluating the Page and creating the necessary PageMetadata as well as the prev and next links to navigate the pages. By default - and this is probably the interesting part here - it will use a plain SimplePagedResourceAssembler (an inner class of PRA) to transform the individual elements of the page into nested Resource instances.
To allow to customize this, PRA has additional toResource(…) methods that take a delegate ResourceAssembler to process the individual items. So you end up with something like this:
class UserResource extends ResourceSupport { … }
class UserResourceAssembler extends ResourceAssemblerSupport<User, UserResource> { … }
And the client code now looking something like this:
PagedResourcesAssembler<User> parAssembler = … // obtain via DI
UserResourceAssembler userResourceAssembler = … // obtain via DI
Page<User> users = userRepository.findAll(new PageRequest(0, 10));
// Tell PAR to use the user assembler for individual items.
PagedResources<UserResource> pagedUserResource = parAssembler.toResource(
users, userResourceAssembler);
Outlook
As of the upcoming Spring Data Commons 1.7 RC1 (and Spring HATEOAS 0.9 transitively) the prev and next links will be generated as RFC6540 compliant URI templates to expose the pagination request parameters configured in the HandlerMethodArgumentResolvers for Pageable and Sort.
The configuration you've shown above can be simplified by annotating the config class with #EnableSpringDataWebSupport which would let you get rid off all the explicit bean declarations.
I wanted to convert list of Resources to page. but when giving it PagedResourcesAssembler it was eating up the internal links.
This will get your List paged.
public class JobExecutionInfoResource extends ResourceSupport {
private final JobExecutionInfo jobExecution;
public JobExecutionInfoResource(final JobExecutionInfo jobExecution) {
this.jobExecution = jobExecution;
add(ControllerLinkBuilder.linkTo(methodOn(JobsMonitorController.class).get(jobExecution.getId())).withSelfRel()); // add your own links.
}
public JobExecutionInfo getJobExecution() {
return jobExecution;
}
}
Paged resource Providing ResourceAssembler telling Paged resource to use it, which does nothing simply return's it back as it is already a resource list that is passed.
private final PagedResourcesAssembler<JobExecutionInfoResource> jobExecutionInfoResourcePagedResourcesAssembler;
public static final PageRequest DEFAULT_PAGE_REQUEST = new PageRequest(0, 20);
public static final ResourceAssembler<JobExecutionInfoResource, JobExecutionInfoResource> SIMPLE_ASSEMBLER = entity -> entity;
#GetMapping("/{clientCode}/{propertyCode}/summary")
public PagedResources<JobExecutionInfoResource> getJobsSummary(#PathVariable String clientCode, #PathVariable String propertyCode,
#RequestParam(required = false) String exitStatus,
#RequestParam(required = false) String jobName,
Pageable pageRequest) {
List<JobExecutionInfoResource> listOfResources = // your code to generate the list of resource;
int totalCount = 10// some code to get total count;
Link selfLink = linkTo(methodOn(JobsMonitorController.class).getJobsSummary(clientCode, propertyCode, exitStatus, jobName, DEFAULT_PAGE_REQUEST)).withSelfRel();
Page<JobExecutionInfoResource> page = new PageImpl<>(jobExecutions, pageRequest, totalCount);
return jobExecutionInfoResourcePagedResourcesAssembler.toResource(page, SIMPLE_ASSEMBLER, selfLink);
}
ALTERNATIVE WAY
Another way is use the Range HTTP header (read more in RFC 7233). You can define HTTP header this way:
Range: resources=20-41
That means, you want to get resource from 20 to 41 (including). This way allows consuments of API receive exactly defined resources.
It is just alternative way. Range is often used with another units (like bytes etc.)
RECOMMENDED WAY
If you wanna work with pagination and have really applicable API (hypermedia / HATEOAS included) then I recommend add Page and PageSize to your URL. Example:
http://host.loc/articles?Page=1&PageSize=20
Then, you can read this data in your BaseApiController and create some QueryFilter object in all your requests:
{
var requestHelper = new RequestHelper(Request);
int page = requestHelper.GetValueFromQueryString<int>("page");
int pageSize = requestHelper.GetValueFromQueryString<int>("pagesize");
var filter = new QueryFilter
{
Page = page != 0 ? page : DefaultPageNumber,
PageSize = pageSize != 0 ? pageSize : DefaultPageSize
};
return filter;
}
Your api should returns some special collection with information about number of items.
public class ApiCollection<T>
{
public ApiCollection()
{
Data = new List<T>();
}
public ApiCollection(int? totalItems, int? totalPages)
{
Data = new List<T>();
TotalItems = totalItems;
TotalPages = totalPages;
}
public IEnumerable<T> Data { get; set; }
public int? TotalItems { get; set; }
public int? TotalPages { get; set; }
}
Your model classes can inherit some class with pagination support:
public abstract class ApiEntity
{
public List<ApiLink> Links { get; set; }
}
public class ApiLink
{
public ApiLink(string rel, string href)
{
Rel = rel;
Href = href;
}
public string Href { get; set; }
public string Rel { get; set; }
}

FXML controller class too large

So I've been practising with JavaFX for a while now and while I love it, I find that my application is growing in size- especially in terms of the number of lines of codes for my FXML Controllers.
Right now a typical package for each scene in my application looks like this:
MyFXML.fxml
MyFXMLController.java
MyDataModel.java
For example, I have a form that takes in some information from textfields, comboboxes and radio buttons. When a button is pressed the form information is saved to a database and is also updated immediately in the tableview.
The tableview also allows deleting and updating of the information displayed.
With only a few components (approx. 10) I have a Controller class file that is about 550 lines long with about a 100 of it taken up by the injections (#FXML) and imports and growing!
My application would ideally have multiple of these different kinds of forms and a controller for each. The database queries are all different so it's not quote possible to abstract them out yet. Also, event listeners for the tableview generally require longer code in javafx than other components.
I just feel like there's a better approach to GUI building in javafx than what I'm doing and was wondering if there was some kind of reference I could look up?
I've read up on other stackoverflow answers on the Single Responsibility Principle. If the code below is any hint, my application simply creates a new staff member and allows updating the information. So I'm confused as to whether my class is too file or is this normal for GUI programming?
I'm not asking for coding help, I'm looking for recommendations on how I can improve GUI programming in javafx.
Thank you!
--
FWIW, here's what a sample controller file looks like
package myApp.staff;
//30 something lines of imports...
public class NewStaffMemberController implements Initializable {
//80 something lines of private variables and #FXML injections
public void setConn(Connection aConn) {
conn = aConn;
wrapGenderRadioButtons();
populateDates();
populateStaffTypeComboBox();
populateDepartmentComboBox();
populateStaffTable();
}
private void wrapGenderRadioButtons() {
//4 lines
}
private void populateDates() {
//25 lines
}
private void populateStaffTypeComboBox() {
//20 lines
}
private void populateDepartmentComboBox() {
//22 lines
}
private void populateStaffTable(){
//longest at 100 lines. This code also adds the event listener for the tableview- makes it quite long!
}
private void editSelectedTableRow(Staff selectedstaff){
//4 lines
}
#FXML
private void selectedRadioBtnAction() {
//1 lines
}
#FXML
private void handleYearComboBoxAction() {
//1 lines
}
#FXML
private void handleMonthComboBoxAction() {
//1 lines
}
#FXML
private void handleDayComboBoxAction() {
//1 lines
}
#FXML
private void staffTypeComboBoxAction() {
//1 lines
}
#FXML
private void departmentComboBoxAction() {
//1 lines
}
#FXML
private void btnGenerateStaffId() {
//36 lines
}
#FXML
private void btnSaveInformation(){
13 lines
}
private Boolean validateData() {
//43 lines
}
private void assignStaffId() {
//12 lines
}
private void insertIntoDatabase() {
//35 lines
}
private void updateDatabase(){
//35 lines
}
#Override
public void initialize(URL url, ResourceBundle rb) {
}
}
Well, I think you don't have choice to inject your fxml fields you need. But maybe if you have number of injections like that just in one controller, you should maybe do a better conception of your app, by doing sub controllers working each other together and don't have everything in just one controller. One view doesn't mean one controller. You can have one view and multiple controller with there own view

Resources