Skip to content

Latest commit

 

History

History
567 lines (340 loc) · 22.9 KB

Errata.adoc

File metadata and controls

567 lines (340 loc) · 22.9 KB

Errata for Pro Spring 6

Hi guys, I am really thankful to all of you that have bought the book and have contributed to finding mistakes in it and in the code, and asking questions about details that seem unclear.


Chapter 3: Introducing IoC and DI in Spring

On page 49, in the note in the middle of the page, in the first sentence, there is a typo.

Original sentence:

You might notice that the interface and class in this example have np type accessor.

Correction:

You might notice that the interface and class in this example have no type accessor.

(Submitted by Albert Attard)


On page 60, at the bottom of the page there is this statement The @Autowired annotation is not used to decorate the constructor…​, but Listing 13-3 shows the @Autowired annotation on the constructor. The warning box on the following page mentions that the annotation is redundant and why. However, keeping the annotation in Listing 13-3, even if not a grave technical error, might be confusing so this was an oversight on my part, that I will correct in the next edition.

(Submitted by Nikolas Poniros)


On page 66 the output in Listing 3-19 should be:

Name: John Mayer
Age: 40
Age in Seconds: 1241401112
Height: 1.92
Is Developer?: false

(Submitted by Albert Attard)


On page 84 there is a mistake in the paragraph before the Explicit Bean Name Section.

context.getBeansOfType(String.class) should be context.getBeansOfType(SimpleBean.class)

(Submitted by Albert Attard)


On page 86 the type for the value() and name() methods should be String[] as defined in the @Bean annotation source code.

(Submitted by Albert Attard)


On page 86, in code Listing 3-49 and before class NonSingletonDemo is mentioned instead of class Singer.

(Submitted by Albert Attard)

Chapter 4: Advanced Spring Configuration and Spring Boot

On page 106, there is a small typo. Learning more about the Spring aplication context…​ should be Learning more about the Spring application context…​

(Submitted by Nikolas Poniros)


On page 114, there is a small typo. The first paragraph under section title Using the JSR-250 @PostConstruct Annotation , Chapter 4 is being references. It should be Chapter 3.

(Submitted by Nikolas Poniros)


On page 116, there is a small typo. The 2 footnote references should be in superscript.

(Submitted by Nikolas Poniros)


On page 127, there is a small typo. The caution box states that Spring automatically calls the getObject() method is a bad practice call that method manually. It should be Spring automatically calls the getObject() method; is a bad practice to call that method manually.

(Submitted by Nikolas Poniros)


On page 135 , in Listing 4-22 the class CustomPropertyEditorRegistrar is part of the code but not used. Also, the ValuesHolder class should be a top class, at the same level with DiverseValuesContainer. The correct code is this repo.

(Submitted by Amit Kumar)


On page 141, there is a small typo. There is a space between ReloadableResource and BundleMessageSource which messes up the actual class name. Should be ReloadableResourceBundleMessageSource.

(Submitted by Nikolas Poniros)


On page 143, in Listing 4-28 the name of one of the message resource file shown in the comment is wrong. The listing shows #labels_de_DE.properties, should be #labels_uk_UA.properties.

(Submitted by Albert Attard)


On page 143, in the description of getMessage() method the message used as example is msg=The quick brown fox jumped over the lazy dog and this doesn’t match the msg in Listing 4-28. It should be msg=Witnessing and not stopping evil is condoning it.

Also, on page 143, in the description of getMessage() method, the nameMsg key value is shown as My nameis {0} {1}. It should be My name is {0} {1}

(Submitted by Nikolas Poniros)


On page 147 under section Considerations for Event Usage, the statement the update component explicitly notifies the cache that the user details have changed should be the update component explicitly notifies the cache that the product details have changed.

(Submitted by Nikolas Poniros)


On page 149 there is this statement:

Notice that for both the file: and http: protocols, Spring returns a UrlResource instance. Spring does include a FileSystemResource class, thus the DefaultResourceLoader does not use this class at all.

This statement is confusing, should be replaced with:

Notice that for both the file: and http: protocols, Spring returns a UrlResource instance. Spring does include a FileSystemResource class, albeit the DefaultResourceLoader does not use this class at all.

(Submitted by Nikolas Poniros)


On page 156 the output snippets at the bottom of the page. This was caused by a wrong import statement in the code. The import has now been corrected and the expected outputs are:

Running the ProfileDemo class with the JVM -Dspring.profiles.active="kindergarten" argument produces the following output:

DEBUG: AbstractEnvironment - Activating profiles [kindergarten]
INFO : ProfileDemo - Food: Milk
INFO : ProfileDemo - Food: Biscuits

This is exactly what the implementation of the kindergarten provider will produce for the lunch set. Now change the profile argument from the previous listing to high school (-Dspring.profiles.active="highschool"), and the output will change to the following:

DEBUG: AbstractEnvironment - Activating profiles [highschool]
INFO : ProfileDemo - Food: Coke
INFO : ProfileDemo - Food: Hamburger
INFO : ProfileDemo - Food: Fries

(Submitted by Ahmed Hadaka)

Chapter 5: Spring AOP

On page 201 there is this statement:

Consider the earlier example of the after-returning advice designed to catch weak keys generated by the KeyGenerator class.

This example was removed from the book because its complexity might distract from the advice implementation, but it was kept in the code repository. However, the above statement should be replaced with Consider the example of the after-returning advice designed to catch weak keys generated by the KeyGenerator class(example in the code repository, class KeyGeneratorAdviceDemo). in future editions of this book.

(Submitted by Nikolas Poniros)


On page 209 there is this statement:

Notice that we have used the same advice class as in the static pointcut example. However, in this example, only the first two calls to sing({key}) should be advised. The dynamic check prevents the third call to sing("E") from being advised, and the static check prevents the sing() method from being advised.

This statement is somewhat confusing, mostly because of mentioning both static and dynamic advice. In future editions of this book, this statement should be changed to:

Notice that we have used the same advice class(DefaultPointcutAdvisor) as in the static pointcut example. However, in this example, only the first two calls to sing({key}) should be advised. The dynamic check prevents the third call to sing("E") from being advised, while the static check prevents any method but sing() method from being advised, ignoring the arguments altogether.

(Submitted by Nikolas Poniros)


On page 209, Listing 5-14 is missing the proxy.sing("c") call output. This might have been intentional, to keep the output small. In future editions, the missing output will be mentioned.

(Submitted by Nikolas Poniros)


On page 226, the following statement:

As you can see, when the sing() method is first invoked outside the control flow of the test() method, it is unadvised.

Should be replaced with

As you can see, when the foo() method is first invoked outside the control flow of the test() method, it is unadvised.

(Submitted by Nikolas Poniros)


On page 230, the following statement:

The first thing to notice in this example is the set of three private MethodMatcher implementations. SingMethodMatcher matches all methods that start with get.

Should be replaced with

The first thing to notice in this example is the set of three private MethodMatcher implementations. SingMethodMatcher matches all methods that start with si.

(Submitted by Nikolas Poniros)


On page 230, the following statement:

TalkMethodMatcher is very specific and matches only the talk() method. This MethodMatcher is combined with ComposablePointcut by using intersection() for the third round for invocations.

Should be replaced with

RestMethodMatcher matches only methods with names ending in`st`. This MethodMatcher is combined with ComposablePointcut by using intersection() for the third round for invocations.

(Submitted by Nikolas Poniros)

Chapter 6: Spring Data Access with JDBC

On page 311, the following paragraph:

Each time the insertWithAlbum() method is called, a new instance of InsertSingerAlbum is constructed because the BatchSqlUpdate class is not thread safe. Then we use it just like SqlUpdate. The main difference is that the BatchSqlUpdate class will queue up the insert operations and submit them to the database in batch.

I seem to have gotten my wires seriously crossed when I wrote this paragraph. It should be replaced in future revisions with:

The BatchSqlUpdate class extends SqlUpdate and provides the capability to batch update operations. Is not thread safe, thus a new instance needs to be created for each use, or call reset() before reuse within the same thread.

(Submitted by Nikolas Poniros)


On page 322, in the following paragraph:

Any code that might distract you from the TestContainers central configuration was stripped away from the StoredFunctionV1TestTest class, the class where the TestContainersConfig is declared. It was declared inside the test class because this is the only place where it is used.

The class name StoredFunctionV1TestTestTest, should be StoredFunctionV1TestTest.

(Submitted by Nikolas Poniros)

Chapter 7: Spring with Hibernate

Starting with page 376, in the Introducing jOOQ section it is mentioned that jOOQ version 3.15 was not on Maven Central, and needed to be installed manually. After the book went into production however,version 3.18.5 of jOOQ became available on Maven Central, and so I updated the project setup, so manual installation is no longer necessary. This allowed me to keep the jOOQ submodules as part of the project build. This also means that every mention of manual installation in this section, is now deprecated and can be ignored.

(Submitted by Nikolas Poniros)

Chapter 8: Spring with JPA

On page 411, the first paragraph in the Updating Data section has a typo: statement and as you’ve seen, s single method should be and as you’ve seen, a single method

(Submitted by Nikolas Poniros)


On pages 414 and 415, Listing 8-25 has been the victim of a bad copy-paste. As a consequence the explanation does not match the listing. The actual content, that matches the explanation is shown below.

Listing 8-25. The SingerServiceImpl.findAllByNativeQuery(..) method.

package com.apress.prospring6.eight.service;
// import statements omitted

@Service("jpaSingerService")
@Repository
@Transactional
public class SingerServiceImpl  implements SingerService {

    public static final String ALL_SINGER_NATIVE_QUERY =
            "select ID, FIRST_NAME, LAST_NAME, BIRTH_DATE, VERSION from SINGER";

    @Override
    public Stream<Singer> findAllByNativeQuery() {
        return em.createNativeQuery(ALL_SINGER_NATIVE_QUERY, Singer.class).getResultList().stream();
    }
    // other methods and setup omitted
}

(Submitted by Nikolas Poniros)


Important
Starting with page 417, the version I have of Chapter 8 differs from the one that was published. No idea how at least three people including myself, have missed this. I remember my technical reviewer asking for something else to be added instead of the Using the JPA Criteria API for a Criteria Query section, and I did it, but somehow my version of the chapter is not the one that made it to production. This being said here is actual end of Chapter 8, that replaces the Using the JPA Criteria API for a Criteria Query and Summary

End of Chapter 8

The stored procedure used for this example, does the same thing as the stored function, given a singer id it extracts its first name. Since stored procedures do not return results, the result of the operation is stored into a procedure output parameter named fn_res. The SQL declaration of this procedure is shown in Listing 8-30.

Listing 8-30. Stored procedure SQL code.

CREATE OR REPLACE PROCEDURE getFirstNameByIdProc(IN in_id INT, OUT fn_res VARCHAR(60))
BEGIN
    SELECT first_name INTO fn_res FROM SINGER WHERE id = in_id;
END

The @NamedStoredProcedureQuery annotation is used to declare a stored procedure query in Chapter 7 as well, only the procedure is invoked using Hibernate session. Invoking a stored procedure configured with @NamedStoredProcedureQuery using a EntityManager is even more practical, since they are boh part of the Jakarta API. Listing 8-31 depicts the invocation of a stored procedure configured using @NamedStoredProcedureQuery with EntityManager.

Listing 8-31. Using EntityManager to invoke a Stored Procedure.

package com.apress.prospring6.eight.service;
// other class details omitted

/*
@NamedStoredProcedureQuery(
		name = "getFirstNameByIdProc",
		procedureName = "getFirstNameByIdProc",
		parameters = {
				@StoredProcedureParameter(
						name = "in_id",
						type = Long.class,
						mode = ParameterMode.IN
				),
				@StoredProcedureParameter(
						name = "fn_res",
						type = String.class,
						mode = ParameterMode.OUT
				)
		}
)
*/
public class SingerServiceImpl  implements SingerService {

    @Override
    public String findFirstNameByIdUsingProc(Long id) {
        StoredProcedureQuery query = em.createNamedStoredProcedureQuery("getFirstNameByIdProc");
        query.setParameter( "in_id", 1L );

        query.execute();
        return (String) query.getOutputParameterValue( "fn_res" );
    }
}

Summary of Chapter 8

In this chapter, we covered the basic concepts of JPA and how to configure JPA’s EntityManagerFactory in Spring by using Hibernate as the persistence service provider. Then we discussed using JPA to perform basic database operations. Advanced topics included native queries and the strongly typed JPA Criteria API.

The purpose of this chapter was to introduce you to JPA’s EntityManagerFactory, because from an architectural point of view, Hibernate’s SessionFactory is an extension of it. Thus, the SessionFactory is also a JPA EntityManagerFactory, which means both contain the entity mapping metadata and allow you to create a Hibernate Session or a EntityManager.

However, the EntityManagerFactory is the standard implementation, it is the same across all the implementations. This means, although not very likely, if you would like to change your JPA provider, in this case Hibernate, with some other persistence implementation (let’s say Oracle TopLink), it is way easier to do it when your code is not tied to it.

This being said, let’s complete the whole picture of working with SQL databases in Spring, by learning about transactions, in the next chapter.

Chapter 9: Spring Transaction Management

On page 430, at the bottom of the page there is a typo: the hasSavepoint() method is referred to as hasSavePoint(). (Submitted by Nikolas Poniros)

Chapter 10: Spring Data with SQL and NoSQL Databases

On page 474 and 745, the @Modifying annotation is referred to as @Modified. (Submitted by Nikolas Poniros)


On page 487, at the bottom of the page this statement:

With this configuration, what happens under the bonnet is that audit event listeners (instances of types implementing org.hibernate.envers.event.spi.EnversListener) are attached to persistence events: add, insert, update and delete.

Should be replaced with:

With this configuration, what happens under the bonnet is that audit event listeners (instances of types implementing org.hibernate.envers.event.spi.EnversListener) are attached to persistence events: insert, update and delete.

(Submitted by Nikolas Poniros)

Chapter 11: Validation, Formatting and Type Conversion

On page 527, at the end of section Validation in Spring, the paragraph should be split in two statements, by a .(dot).

The other one is via Spring’s support of JSR-349 (Bean Validation). We present both of them in the coming sections.

(Submitted by Nikolas Poniros)


On page 532, there is a statement that is not grammatically correct.

Notice the body of the supports(..) method. The BloggerWithAddress.class.isAssignableFrom(clazz) statement validates that the target object is either an instance of BloggerWithAddress, either an instance of its superclass.

Should be replaced with:

Notice the body of the supports(..) method. The BloggerWithAddress.class.isAssignableFrom(clazz) statement validates that the target object is either an instance of BloggerWithAddress, or an instance of its superclass.

(Submitted by Nikolas Poniros)

Chapter 12: Task Scheduling

On page 559 in Listing 12-10, there is a piece of code missing, from the CarServiceImpl#updateCarAgeJob that throws a IllegalStateException that is referenced in page 569.

Listing 12-10. CarServiceImpl class.

public class CarServiceImpl implements CarService {

    @Scheduled(fixedDelay=10000)
    public void updateCarAgeJob() {
        //...
        // randomly failing the task so we can add exception handling
        if (System.nanoTime() % 5 == 0) {
            throw new IllegalStateException("Task no " + Thread.currentThread().getName() + " is dead, dead dead...");
        }
        //...
    }

}

(Submitted by Nikolas Poniros)


On page 564 in Listing 12-19, there is a piece of code missing, from the AsyncServiceImpl#asyncTask that throws a IllegalStateException that is referenced in page 569.

Listing 12-19. AsyncServiceImpl bean class.

public class AsyncServiceImpl implements AsyncService {

    @Async
    @Override
    public void asyncTask() {
        // ...
        // randomly failing the task so we can test exception handling
        if (System.nanoTime() % 5 == 0) {
            throw new IllegalStateException("Task no " + Thread.currentThread().getName() + " is dead, dead dead...");
        }
        //..
    }
}

(Submitted by Nikolas Poniros)

Chapter 13: Spring Remoting

On page 577, there is a typo in the following statement:

The Category enum is used to categorize letters based on tier scope.

Should be replaced with:

The Category enum is used to categorize letters based on their scope.

(Submitted by Nikolas Poniros)


On page 579, highlighted text in Listing 13-14 is referenced, but there is no such text. Recommended correction: the "mailbox" property in Listing 13-14 should be in bold.

(Submitted by Nikolas Poniros)


On page 595, small typo: convertor should be converter.

(Submitted by Nikolas Poniros)


On page 600, small typo: Not should be Now at the beginning of the page.

(Submitted by Nikolas Poniros)

Chapter 14: Spring Remoting

On page 658, small typo: LONGBLOG should be LONGBLOB.

(Submitted by Nikolas Poniros)


On page 660, Listing 14-30 is missing the customized error messages. The correct Listing is shown below:

Listing 14-30 The Spring bean necessary to support file uploading.

package com.apress.prospring6.fourteen.util;
import jakarta.validation.constraints.*;
// other import statements omitted

public class SingerForm {

    @NotEmpty(message="{NotEmpty.firstName}")
    @Size(min=2, max=30, message="{Size.firstName}")
    private String firstName;

    @NotEmpty(message="{NotEmpty.lastName}")
    @Size(min=2, max=30, message="{Size.lastName}")
    private String lastName;

    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDate birthDate;

     MultipartFile file;

   // getters and setters omitted
}

(Submitted by Nikolas Poniros)


On page 661 , before Listing 14-32, there is a reference to Listing 14-28, should be 14-31.

(Submitted by Nikolas Poniros)

Chapter 15: Spring Remoting

On page 685 ,in the first paragraph there is a small typo: there is no ned for should be replaced with there is no need for.

(Submitted by Nikolas Poniros)

Chapter 17: Spring Remoting

On page 783, this statement in the first paragraph:

If for some reason you cannot use the Spring Security default schema, yo must provide a custom implementation of UserDetailsService that is responsible for retrieving users and authorities based on user provided data.

must be changed with:

If for some reason you cannot use the Spring Security default schema, a custom implementation of UserDetailsService needs to be provided that is responsible for retrieving users and authorities based on user provided data.

(Submitted by Nikolas Poniros)

Chapter 18: Monitoring Spring Applications

On page 800, in the statement under Figure 18-3 there a { that should not be there in the findSinger({"John", "Mayer") operation.

(Submitted by Nikolas Poniros)

Chapter 19: Spring WebSocket Support

On page *829*, in Listing 19-4, the first if (websocket !== "undefined") statement should be if (typeof websocket !== "undefined")

(Submitted by Nikolas Poniros)


On page *835*, Figure 19-4 caption starts with SocketJS instead of SockJS

(Submitted by Nikolas Poniros)

Chapter 20: Reactive Spring

On page 868 , statement Two things need to be clarified about the sample in Listing 2-13:, should be referencing Listing 20-13.

(Submitted by Nikolas Poniros)


On page 882 the .(dot) separating the two statements in the paragraph is missing:

However, what is interesting to test is a negative scenario For example when we try to create another John Mayer, as shown in Listing 20-22.

Should be: However, what is interesting to test is a negative scenario. For example when we try to create another John Mayer, as shown in Listing 20-22.

(Submitted by Nikolas Poniros)

Appendix A

On page 902 and 906, the jOOQ submodules are mentioned as not being part of the build configuration, as per the old version of the project that used jOOQ 3.15. Feel free to ignore the notice box.

(Submitted by Nikolas Poniros)