Friday, December 29, 2017

Updating Book for New Edition

I am using SVN with Netbeans to store the contents of the book.

To avoid the issue with the project files being added to the repo, I have added the repo source files to a working directory and created a Netbeans project in a different folder, pointing the sources of the project to the working directory files.

I avoid using the NetBeans SVN and use a separate program. On the Mac I have used svnX, but it has problems with the newer OS. I am trying SmartSVN 9.2. I have a 31 day free, professional trial before reverting to a simple, free version.

I stored the source for the images in a separate repo. The branch only has the final version of each image.

The ROOT servlet on the website has an index. Controller that intercepts book and translates to the correct edition of the book.

I use an Index controller to access the chapters.

When setting up project on new computer:
  1. checkout repo
  2. create netbeans project from existing sources
  3. allow ssi in web.xml
  4. allow listings in web.xml
  5. edit tomcat-users 
  6. set context as privileged
One of the projects is a Maven project. After checking out the repo, download dependencies.






Friday, June 23, 2017

Spring MVC in NetBeans

First Spring MVC Application

I am trying the tutorial for Spring MVC in NetBeans.

The tutorial recommends implementing a service, separate from the controller, to handle the business logic.
  1. Set up a Spring MVC project in NetBeans and run it.
  2. The tutorial uses Spring 3 and SimpleFormController, which is not available in Spring 4. Select Spring 3 when creating the project.
  3. All .htm files are set to map to the dispatcher.
  4. The welcome file is set to redirect.jsp
  5. Redirect.jsp contains a redirect to index.htm.
  6. The dispatcher servlet is part of the Spring framework, part of Spring MVC.
  7. The name of the dispatcher servlet is 'dispatcher', so its associated config file is named 'dispatcher-servlet'.
  8. The dispatcher config file defines three beans, for URL mapping, a view resolver, and a view controller.
  9. The URL mapping associates names or references for beans. Use urlMap to associate a URL to a bean reference. Use mappings to associate a URL with a bean name.
  10. The view resolver expands names into full paths.
  11. The index controller is the controller that displays the index page. It is a class from Spring. It is accessed with a logical name. The view resolver will expand the logical name to a full path.
  12. The application has a view that accepts a name and a view that displays the name.
  13. The controller decides which view to display. The controller sends a model to the view. The model contains data for the view to display. The name of the controller is HelloController.
  14. Business logic is separated from the controller into a service. A service is a logical category, it is just another java class. The business logic will process the name from the form.
  15. Create the java class for the service named HelloService. The service has a method that echoes 'Hello some-name!'. The parameter is some-name.
  16. The tutorial makes use of the deprecated Simple Form Controller, but recommends using annotated controllers. It must use Spring 3 for this, not Spring 4.
  17. The SimpleFormController defines a command, a success view and a form view.
  18. The command is the name of the class to send to the form. The form will use tags defined in Spring that use properties from a bean to populate the form.
  19. The sucessView is the view to show if validation succeeds.
  20. The formView is the view for entering data and the view to show if errors exist.
  21. Create the Name class to pass to the form. Add a property to the class for a value. Properties are variables with setters and getters.
  22. The onSubmit command is overridden in the SimpleFormController. It accepts the request, response, command, and errors. The command is the object that has the data from the form. The errors can be filled with error messages and sent back to the form. The method returns a ModelAndView which is returned from the getSuccessView method. Objects can be added to the model with addObject, like adding a value to a map.
  23. In HelloController, create a property for the service. The getter is not needed.
  24. Add a bean definition to applicationContext.xml for HelloService. 
  25. Add a bean definition to dispather-servlet.xml for HelloController.
  26. The helloView echoes the helloMessage using EL (Expression Language).
  27. The nameView contains the form. Add a taglib for the Spring tags.
  28. Use spring:nested path to associate the command with the form.
  29. In the form, use spring:bind to associate a field with a property in the bean. In the body of the tag, use status.expression and status.value in EL to retrieve the name and value of the associated property.
  30. Instead of changing the entry point of the application, I modified the index.jsp with a link to hello.htm, from the current location.
  31. The mapping for the hello controller is handled by ControllerClassNameHandlerMapping from the Spring framework. Add a bean definition to dispatcher-servlet.xml for this bean. The default mapping is from HelloController to hello.htm.

Step-by-Step Spring MVC Application

My next attempt will be another tutorial from Netbeans, Spring MVC Step-byStep.

The tutorial is using Spring 2.5, I am using Spring 4.

Part 1 - Hello Example

The first change is that the default page is index.jsp in the tutorial, but redirect.jsp in Spring 4.

The tutorial recommends changing the welcome file list and editing the index page so it does not redirect, but generates a static page. I chose not to do that.

The tutorial uses GlassFish, I am using Tomcat.

I created the project using the NetBeans templated for a Spring MVC project.

The tutorial recommends adding a bean with the name of 'hello.html', but the name should be resolved normally through the ControllerClassHandlerMapping bean that was added to the dispatcher-servlet.xml automatically when NetBeans created the Spring MVC project. Update: the tutorial starts implementing relationships manually and then later introduces a view resolver.

In the handleRequest method, the ModelAndView is created with "hello.jsp", it should be created with "hello", then the Mapping controller will find it.

Part 2 - Inventory Example

Instead of changing HelloController, I implemented InventoryController as a new controller.
  1. Create an include file for jstl/core and jstl/fmt. The taglib for Spring forms is now part to the Spring framework, so it does not have to be included.
  2. At this point, the tutorial uses a InternalResourceViewResolver class to decouple the view from the controller, by using a logical name for the view page.

Part 3 - Business Logic

  1. Add a class for a Product, with price and description.
  2. Add am interface for a ProductManager for handling products. It contains a business method for increasing the price for all products, and a method to retrieve all products. Add other methods for manipulating the product class.
  3. The controller will access the interface and Spring will supply an appropriate implementation. (Interfaces also allow for JDK proxying.)
  4. Create a concrete class that implements the manager interface.

Part 4 - Web Interface

  1. Create a controller. Add a product manager property. Return a view that displays the records from the list in the product manager.
  2. Display the records in the view.
  3. Use a resource bundle to customize the appearance of the form.
  4. Create some static test data.
  5. Use spring-form.tld to bind the form data in the view to the model. The tutorial shows how to install the form taglib, but it is part of Spring 4.
  6. Add a style sheet for displaying errors in red.
  7. The tutorial redirects to home.htm, but I created a new controller for inventory, so I redirected to inventory.htm.
  8. Create a price increase class. Add a property for an integer percentage.
  9. Create a validator that extends org.springframework.validation.Validator. Override the supports and validate methods. Test that the percentage is not too small or too large.
  10. Add a form controller, that displays the form, accepts a percentage and modifies the product prices. In the controller, test the BindingResult parameter after the call, to see if errors exist.
  11. Aarrgghhh! I have built this in Spring 4, but it requires SimpleFormController from Spring 3! I may be saved. A post on converting from SimpleFormController uses the exact example from this tutorial. The example is not exactly the same: pass the price increase object to the validator; priceIncrease should be priceincrease when validation fails; redirect to inventory.htm, not home.htm, to show the inventory with the increased prices.
  12. I used annotations to implement the controller in Spring 4.
    1. I modified the dispatcher-servlet.xml file to add support for annotation scanning and for the MVC annotations. The file begins as:
      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:mvc="http://www.springframework.org/schema/mvc"
             xmlns:p="http://www.springframework.org/schema/p"
             xmlns:aop="http://www.springframework.org/schema/aop"
             xmlns:tx="http://www.springframework.org/schema/tx"
             xmlns:context="http://www.springframework.org/schema/context"
             xsi:schemaLocation="http://www.springframework.org/schema/beans 
                 http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
                 http://www.springframework.org/schema/aop 
                 http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
                 http://www.springframework.org/schema/mvc
                 http://www.springframework.org/schema/mvc/spring-mvc.xsd
                 http://www.springframework.org/schema/tx 
                 http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
                 http://www.springframework.org/schema/context
                 http://www.springframework.org/schema/context/spring-context.xsd">
      
          <mvc:annotation-driven />
          <context:component-scan base-package="springapp"/>
      
      

  13. The controller is mapped with the logical name 'increase', but it will be entered as 'increase.htm' and then resolve to 'increase'.
  14. One method handles GET, the other handles POST.
  15. In the GET handler, populate the model with the products from the product manager.
  16. In the POST handler, validate that the percentage is good, then use the product manager to increase the price. Use the ModelAttribute annotation to fill a parameter with the values of the elements from the form.
  17. Resolve to the inventory, to see the changes in the prices.
  18. The product manager and validator will be injected by Spring.

  19. @Controller
    @RequestMapping("/increase") //controller namer will resolve increase.htm to here
    public class IncreaseController {
    
        @Autowired
        ProductManager productManager;
    
        @Autowired
        private ProductPriceIncreaseValidator priceIncreaseValidator;
    
        @RequestMapping(method = RequestMethod.POST)
        public String onSubmit(
                @ModelAttribute("priceIncrease") ProductPriceIncrease priceIncrease,
                BindingResult result) {
    
            priceIncreaseValidator.validate(priceIncrease, result);
            if (result.hasErrors()) {
                return "priceincrease";
            }
            // Validator has succeeded. 
            // Perform necessary actions and return to success page. 
            productManager.increasePrice(priceIncrease.getPercentage());
            return "redirect:/inventory.htm";
        }
    
        @RequestMapping(method = RequestMethod.GET)
        public String initializeForm(ModelMap model) {
            // Perform and Model / Form initialization
            model.addAttribute("prod", productManager.getProducts());
            ProductPriceIncrease priceIncrease = new ProductPriceIncrease();
            priceIncrease.setPercentage(20);
            model.addAttribute("priceIncrease", priceIncrease);
            return "priceincrease";
        }
    
    }
    




  20. Add more messages to the resource bundle for the error processing.
  21. Add a link to the price increase controller in the inventory page.

Part 5 - Adding Data Persistence

  1.  I used mysql instead of hsql.
  2. Create the table and populate it with some data.
  3. Create a product data access object (DAO) interface. The interface defines the functionality of access to the database. It is similar to the concept of the product manager interface. By defining the methods that manipulate the database using an interface, one of several implementations could be injected by Spring.
  4. Create the class that implements the DAO interface.
    1. The tutorial extends the class from SimpleJdbcDaoSupport and uses SimpleJdbcTemplate, which are deprecated. The replacements are JdbcDaoSupport and JdbcTemplate.
    2. The saveProduct method did not work as described in the tutorial. The MapSqlParameter class threw a Non-Serializable error. I used an object array to substitute positional parameters, instead of named parameters. When I tried to pass an array of types, I received an error that parameter 3 was missing.
          @Override
          public void saveProduct(Product prod) {
              logger.info("Saving product: " + prod.getDescription());
      //        int count = getJdbcTemplate().update(
      //            "update products set description = :description, price = :price where id = :id",
      //            new MapSqlParameterSource()
      //                .addValue("description", prod.getDescription())
      //                .addValue("price", prod.getPrice())
      //                .addValue("id", prod.getId()));
              int count = getJdbcTemplate().update(
                  "update products set description = ?, price = ? where id = ?",
                  new Object[] {prod.getDescription(), prod.getPrice(), prod.getId()});
      //            new Object[] {Types.VARCHAR, Types.DECIMAL, Types.INTEGER}
      //        );
              logger.info("Rows affected: " + count);
          } 
      
  5. Add an id property and toString method to the product class.
  6. The testing example used a deprecated class. I found a resource at Spring By Example that helped translate to annotation syntax. 
    1. @ContextConfiguration has a locations attribute that expects an array of strings containing the location of a config file.
    2. @TransactionConfiguration can specify an addtional config file that apppends -context.xml to the name of the class. I did not use one. I placed all the configuration in the context file. 
    3. JdbcTestUtils has methods that are analogous to the examples from the tutorial.
      package springapp.repository;
      
      import java.util.List;
      import org.junit.Test;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.test.context.ContextConfiguration;
      import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
      import org.springframework.test.context.transaction.TransactionConfiguration;
      import org.springframework.transaction.annotation.Transactional;
      import springapp.domain.Product;
      import static org.junit.Assert.assertEquals;
      import org.springframework.core.io.ClassPathResource;
      import org.springframework.core.io.Resource;
      import org.springframework.test.jdbc.JdbcTestUtils;
      
      @ContextConfiguration(locations={"classpath:test-context.xml"})
      @TransactionConfiguration
      @Transactional(readOnly=true)
      public class ProductDaoTransactionUnitTest extends AbstractTransactionalJUnit4SpringContextTests {
      
          //protected final Log logger = LogFactory.getLog(getClass()); 
      
          protected static int SIZE = 3;
      
          @Autowired
          protected ProductDao productDao = null;
          
          Resource resource; 
          
          @Test
          @Transactional(readOnly=false)
          public void testMain() {
              resource = new ClassPathResource("load_data.sql");
              JdbcTestUtils.deleteFromTables(jdbcTemplate, "products");
              JdbcTestUtils.executeSqlScript(jdbcTemplate, resource, true);
              testListProduct();
              testSaveProduct();     
          }
          
          public void testSaveProduct() {
      
              List products = productDao.getProductList();        
              assertEquals("wrong number of products?", 3, products.size());
              for (Product p : products) {
                  p.setPrice(200.12);
                  productDao.saveProduct(p);
              }        
      
              List updatedProducts = productDao.getProductList();
              for (Product p : updatedProducts) {
                  assertEquals("wrong price of product?", 200.12, p.getPrice(), 0.001);
              } 
      
          }
      
          private void testListProduct() {
              List products = productDao.getProductList();        
              assertEquals("wrong number of products?", 3, products.size());
          }
          
      }
      
    4. test-context.xml
      <?xml version="1.0" encoding="UTF-8"?> 
      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:p="http://www.springframework.org/schema/p"
             xmlns:aop="http://www.springframework.org/schema/aop"
             xmlns:tx="http://www.springframework.org/schema/tx"
             xsi:schemaLocation="http://www.springframework.org/schema/beans 
                  http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
                  http://www.springframework.org/schema/aop 
                  http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
                  http://www.springframework.org/schema/tx 
                  http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
            
          <!-- the test application context definition for the jdbc based tests -->  
          <bean id="productDao" class="springapp.repository.JdbcProductDao">
              <property name="dataSource" ref="dataSource" />
          </bean> 
         
          <bean id="dataSource"
                    class="org.apache.commons.dbcp2.BasicDataSource">
              <property name="driverClassName" value="${jdbc.driverClassName}" />
              <property name="url" value="${jdbc.url}"/>
              <property name="username" value="${jdbc.username}" />
              <property name="password" value="${jdbc.password}" />
          </bean>
              
          <bean id="customerDAO" class="springapp.repository.JdbcProductDao">
              <property name="dataSource" ref="dataSource" />
          </bean>
          
          <bean id="propertyConfigurer" 
                class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
              <property name="locations">
                  <list>
                      <value>classpath:jdbc.properties</value>
                  </list>
              </property>
          </bean>
           
          <bean id="transactionManager" 
                class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
              <property name="dataSource" ref="dataSource" />
          </bean> 
          
          <tx:annotation-driven/>
          
      </beans>
      
  7. next 1
  8. next 2

Part 6 - Integrating the Web Layer with the Persistence Layer

  1. Modify the SimpleProductManager so it is backed by the DAO, instead of a List. Update the list in the DAO after the price increases.
  2. The tutorial adds an applicationContext.xml by adding a listener to web.xml for the Spring ContextLoaderListener. This step was already done by the Spring MVC template.
  3. Move the product manager and DAO classes to the application context XML file.
  4. The commons-dbcp is now commons-dbcp2. I could also use org.springframework.jdbc.datasource.DriverManagerDataSource as the data source class.
  5. I downloaded aopalliance, aspectjweaver and aspectj JAR files and added them to the library.
  6. Once I enabled transactions, I was not allowed to run the query from the tutorial. The advice indicates that save methods in the ProductManager can write to the database, but the method in the ProductManager starts with increase. I changed the advice from save* to increase* and it worked.
  7. To agree with the testing for the DAO, I changed the main application context to use transaction annotations, too. After updating applicationContext.xml, the only change was to add Transactional(readOnly=true) to the SimpleProductManager and add Transactional(readOnly=false).

Spring MVC Hibernate

The next tutorial is an integration of Hibernate with Spring MVC. It uses Spring 3 and Hibernate 3. I will attempt it with Spring 4 and Hibernate 4.
  1. The syntax for creating the table is incorrect. The primary key is EMPID, not ID. A comma is missing before the primary key statement.
  2. The controller class has syntax errors. The Map declaration in listEmployees is missing a comma between String and Object. The prepareListofBean method has the wrong capitalization for EmplyeeBean when declaring the List.
  3. The dispatcher servlet is named sdnext. It is not necessary to indicate the name of the config file, if it is the servletName-context.xml.
  4. Errors in XML for empty element for property-placeholder, component-scan and annotation-drive. Made each into a singleton element.
  5. Build failed. Could not find TransactionInterceptor. Added aopalliance.jar to resolve dependency.
  6. Build failed. Could not find FilterDefinition. This is related to using Hibernate 4 instead of Hibernate 3. Changed the config file to resolve dependency.
     
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    --other properties here
    </bean>
    
    <bean id="hibernateTransactionManager"
        class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
     
  7. Build failed. Added mysql driver.
  8. The web app runs, but the Hibernate session was not created. Add @Transactional to the controller class.
  9.  Cannot find save.html. The action in the add.html form should be to save.html, not /sdnext/save.html. I added the name of the web app with ${pageContext.request.contextPath}.
  10. The value fields in the form input are ignored. I modified the handler in the controller so it accepts the ModelMap first, then the employee and binding results. Using put for the command did not work, but addAttribute did. I removed the local map and used the ModelMap instead.
  11. The column name for the address field is incorrect. In Employee it is empaddress, in the database it is address.
  12. After these changes, I can add a record to the database and it is displayed in the add page.
  13. The edit command does not list the current values in the bean, except for the id. It has the same problem with the ModelMap. Also, the commandName for the form is command, not employee.
  14. The method names for edit and delete are backwards.
  15. The edit method is accessed from the table of employees. The link uses a query string parameter. I changed it to a path variable and retrieved the id from it. The method must use the id to retrieve the bean from the database. The bean is not in the command object. I changed the link so that it includes the name of the web app with ${pageContext.request.contextPath}.
  16. I modified delete the same as edit. Do not send a null command to the form, send a default employee.
  17. I am able to add, list, edit and delete employees.

Learning Aikido

Forty years ago I started learning Aikido. I practiced for a few months and passed a practical exam.

Last year, I started practicing again.

I was a beginner forty years ago, now I am less than a beginner.

Many resources are available on the web. Actually, too many are available. It is difficult to know where to start.

My current teacher is Rene Canabate, a 5th Dan, in the tradition of Morihei Ueshiba and Morihiro Saito.

Before class we stretch and then practice ukemi (falls), both forward and backward.

We begin each class with Tae No Henko. It can be done two ways, Ki No Nagare (flowing) or Awase (blending). Basic techniques are known as kihon.

The attacker is the uke and the defender is the nage, but most important is the relationship between uke and nage.

The uke attacks in several ways:
Morote Dori - two hand grab on one wrist
Shomen Uchi - overhead attack with edge of hand, like a sword attack
Munetski - punch to stomach

The nage has several responses to each attack:
Ikkyo
Nikyo
Sankyo
Yankyo
Gokyo
Kokyu Ho - breath technique
Kotegaeshi

Place the attack with the defense to name the relationship between the uke and nage:
Shomen Uchi Ikkyo
Shomen Uchi Omote Waza
Munetsuki Kotegaeshi 
Munetsuki Omote Waza

The above techniques are the requirements for the 6th kyu exam.

Sensei recommends that students practice 13 jo and 31 jo when not in class. He recommends the teachers Saito Sensei and Yamata.

Saito Sensei Videos

  1. Demonstration
  2. Japanese Promotion 
  3. Demonstration Iriminage
  4. Shomen Uchi
  5. Shomen Uchi Ikkyo with translation. 
  6. Shomen Uchi Sankyo
  7. Shomen Uchi (5th form)
  8. Shomen Uchi Shiho Nage
  9. 20 Jo Suburi
The Aikido glossary is helpful.

There are several Aikido schools that publish kyu requirements.

Aikikai

6th Kyu (Rokukyu) 20 practice days since beginning

  • Seiza (sitting) (a) Rei (bowing) (b) Rise from seiza
  • Shikko* (walking on knees) (mae and ushiro [forward and backward])
  • Hanmi (standing) (a) Migi Hanmi [right foot forward] (b) Hidari Hanmi [left foot forward]
  • Ukemi (rolls) (a) Ushiro ukemi (1) back fall (2) back roll* (b) Mae ukemi* (forward)
  • Kokyu undo (a) Funakogi undo (b) Ikkyo undo
  • Tai sabaki (body movement) (a) Tenkan (b) Irimi (c) Irimi tenkan (d) Tenshin
  • Hanmi (w/partner) (a) Ai hanmi (reversed) (b) Gyaku hanmi (mirrored)
  • Atemi (w/partner) (a) Tsuki (b) Yokomenuchi (c) Shomenuchi
  • Tai no henko (w/partner) as both uke and nage
  • Kokyudosa
* Instructor's option - depending on age and ability.

5th Kyu (Gokyu) 40 days after 6th Kyu, or 60 practice days

Monday, April 24, 2017

Trying Spring Framework

I am following the Spring tutorial at Tutorials Point. The site uses the Eclipse IDE. I am using NetBeans.

First, I created a Java Web application and selected the Spring MVC Framework. I confirmed the choice to include JSTL.

The Spring Framework JAR files and the JSTL JAR files are included.





















The web.xml file includes a reference to a local configuration file, a context listener for the Spring Framework, a servlet that implements the Spring dispatcher, a mapping that sends all .htm files to the dispatcher servlet, a session timeout of 30 minutes, and the name of the welcome file as redirect.jsp.






















The local configuration file is for beans that access a database.

An additional config file is added for the dispatcher servlet. It adds a mapping that refers the index page to the index controller. All other controllers will use the default mappings for Spring. The file also adds rules to transform names into pages. The last tag declares the index controller with its default view.


The redirect.jsp uses embedded java to call the sendRedirect method from the response. The welcome file is redirect.jsp.

The index.htm is significant, since the dispatcher servlet is mapping the file name index.htm to the index controller. If the name in the redirect.jsp is changed, then the key for the property for the indexController must be changed, too.

The index controller sets the view name as index, which forces the viewResolver to create the URL /WB-INF/jsp/index.jsp. Change the prefix to change the path to the JSPs, change the suffix to map to a different type of file.

Normal controllers will use a different naming convention to resolve views. The index controller is different. Any path can be used to map to the index controller, then the index controller will present its view.

Application Context


ApplicationContext is used to create beans. BeanFactory is used to create beans, too. BeanFactory is simpler and its functionality is included in ApplicationContext.

AbstractApplicationContext allows registration of a callback for the destruction of a bean. The destruction callback is not called if scope is set to prototype, since Spring does not manage the entire life cycle of the bean. The initialization and destruction callback names can be set in the opening beans tag in the Beans.xml file. This will set the name of the callbacks for all beans.

To see how the destroy method works, save the application context as an AbstractApplicationContext and call the registerShutdownHook() before closing the application.

BeanPostProcessor


Adding a bean that implements BeanPostProcessor allows for callbacks before and after initialization and destruction.

Injection with XML 

package com.tutorialspoint;

public class TextEditor {
   private SpellChecker spellChecker;
   private GrammarChecker grammarChecker;

    public TextEditor(GrammarChecker grammarChecker) {
        this.grammarChecker = grammarChecker;
    }
  
   // a setter method to inject the dependency.
   public void setSpellChecker(SpellChecker spellChecker) {
      System.out.println("Inside setSpellChecker." );
      this.spellChecker = spellChecker;
   }
  
   // a getter method to return spellChecker
   public SpellChecker getSpellChecker() {
      return spellChecker;
   }
  
   public void spellCheck() {
      spellChecker.checkSpelling();
   }
  
   public void grammarCheck() {
      grammarChecker.checkGrammar();
   }

}


Injection is handled with XML using property and constructor-arg. Use ref when a constructor arg is to a bean. For a setter/getter configuration, use a property that contains an inner bean.

 Autowiring

TutorialsPoint does not go into details about autowiring with XML. Here is another resource: Autowiring with XML

When wiring by name, use the name of the property in the bean, not the name of the variable that the property encapsulates. 

When wiring by type, only one bean of the given type can be a property in the enclosing bean.

Wiring by constructor is wiring byType, but limited to the constructor arguments, not the bean properties.

Annotations

To use annotations to configure Spring, modify the Beans.xml file:
  1. Add xmlns:context
  2. Add schema locations for context and spring-context
  3. Add a tag for context annotation-config
  4. Define the beans in Java, not in the XML.

Java Source Code

Use @Configuration to indicate that Spring should read this class for bean configuration.

Use @Bean on the constructor of the bean class. The annotation indicates that the return from the method is a bean to be registered with Spring. It is equivalent to a bean declaration in the Beans.xml file with the id and class attributes set. All other attributes will have default values. The id must be unique, but is not relevant to retrieving the bean. The class is used to retrieve the bean.

package com.tutorialspoint.annotation;

import org.springframework.context.annotation.*;

@Configuration
public class BeanConfig {
   
   @Bean
   public HelloWorld helloWorld(){
      return new HelloWorld();
   }
 
}


Injection


To implement Dependency Injection, create two methods that return the two classes and annotate them with @Bean. Call the constructor of the dependence class from the constructor of the dependent class.

package com.tutorialspoint.annotation.inject;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class TextEditorConfig {
   @Bean
   public TextEditor textEditor(){
      return new TextEditor( spellChecker() );
   }

   @Bean
   public SpellChecker spellChecker(){
      return new SpellChecker( );
   }
}


Import


The @Import annotation allows one config file to be used in another.

Lifecycle Callbacks


The @Bean annotation supports initMethod and destroyMethod attributes to register callback methods.

Bean Scope


Bean scope is controlled with the @Scope annotation. Use it along with the @Bean annotation. The annotation only has one attribute named value, so the attribute name may be omitted.

MVC


Use @Controller to indicate that a class is a controller.

Use @RequestMapping to set the URL to use to access the controller from the web. The annotation can be used multiple times. It can set the URL and also the method to use. The default parameter is the URL, the method is set with the method attribute.

The return value from the method is the name of the view to use to display the response.

package com.tutorialspoint.annotation.mvc;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("/hello")
public class HelloController {
   @RequestMapping(method = RequestMethod.GET)
   public String printHello(ModelMap model) {
      model.addAttribute("message", "Hello Spring MVC Framework!");
      return "hello";
   }
}


I was able to run all the examples.




Friday, November 18, 2016

Using Task Instead of BackgroundWorker to Update UI

The BackgroundWorker component allows for convenient access to a thread. It supports
  • Reporting Progress
  • Error Handling
  • Returning a Result
  • Cancellation
Updating the UI is a common action in GUI applications that perform a time consuming task. A background worker allows for a simple implementation of updating the UI thread and for the UI thread to control the background worker.

A Task is another way to implement a separate worker thread. I will demonstrate how to transform all the actions performed in a background worker into the context of a Task.

I have used the following resources for Tasks
The example I am using is from the Windows Forms 2.0 book by Chris Sells.

Calculate Pi Example

 The calculations for Pi are a mystery, but they take time.

    void CalcPi(int digits) {
      StringBuilder pi = new StringBuilder("3", digits + 2);

      if( digits > 0 ) {
        pi.Append(".");
     
        for( int i = 0; i < digits; i += 9 ) {
          int nineDigits = NineDigitsOfPi.StartingAt(i + 1);
          int digitCount = Math.Min(digits - i, 9);
          string ds = string.Format("{0:D9}", nineDigits);
          pi.Append(ds.Substring(0, digitCount));
      }
    }

A method encapsulates access to the UI.

    void ShowProgress(string pi, int totalDigits, int digitsSoFar) {
      // Display progress in UI
      this.resultsTextBox.Text = pi;
      this.calcToolStripProgressBar.Maximum = totalDigits;
      this.calcToolStripProgressBar.Value = digitsSoFar;
    }
 
A custom class is used to encapsulate data that is passed to the UI.

    class CalcPiUserState {
      public readonly string Pi;
      public readonly int TotalDigits;
      public readonly int DigitsSoFar;

      public CalcPiUserState(string pi, int totalDigits, int digitsSoFar) {
        this.Pi = pi;
        this.TotalDigits = totalDigits;
        this.DigitsSoFar = digitsSoFar;
      }
    }

Helper methods are used to control modify the appearance of the UI.

        void SetUIReady()
        {
            // Reset progress UI
            this.calcToolStripStatusLabel.Text = "Ready";
            this.calcToolStripProgressBar.Visible = false;
        }

        void SetUIBusy()
        {
            // Set calculating UI
            this.calcToolStripProgressBar.Visible = true;
            this.calcToolStripStatusLabel.Text = "Calculating...";
        }

Starting a Worker Thread that Reports Progress

BackgroundWorker

Handle the DoWork event

    void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) {
        CalcPi((int)e.Argument);
    }

Set  WorkerSupportsProgress property
Handle ReportProgress event

    void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) {
      // Show progress
      CalcPiUserState progress = (CalcPiUserState)e.UserState;
      ShowProgress(
        progress.Pi, progress.TotalDigits, progress.DigitsSoFar);
    }

Call RunWorkerAsync

    void calcButton_Click(object sender, EventArgs e) {
      SetUIBusy();

      // Begin calculating pi asynchronously
      this.backgroundWorker.RunWorkerAsync(
        (int)this.decimalPlacesNumericUpDown.Value);
    }

 Handle RunWorkerCompleted event

    void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
   {
       SetUIReady();  
   }

Modify the CalcPi method so that it reports progress regularly.

    void CalcPi(int digits) {
      StringBuilder pi = new StringBuilder("3", digits + 2);

      CalcPiUserState state = new CalcPiUserState(pi.ToString(), digits, 0);
      // Report initial progress
      this.backgroundWorker.ReportProgress(0, state);

      if( digits > 0 ) {
        pi.Append(".");

        for( int i = 0; i < digits; i += 9 ) {
          int nineDigits = NineDigitsOfPi.StartingAt(i + 1);
          int digitCount = Math.Min(digits - i, 9);
          string ds = string.Format("{0:D9}", nineDigits);
          pi.Append(ds.Substring(0, digitCount));

          // Report continuing progress
          state = new CalcPiUserState(pi.ToString(), digits, i + digitCount);
          this.backgroundWorker.ReportProgress(0, state);

          // Check for cancelation
          if (this.backgroundWorker.CancellationPending) { return; }         
        }
      }
    }

Task

Create a helper method to update the UI from the custom state class.

        void ShowProgressState(CalcPiUserState state)
        {
            try
            {
                // Display progress in UI
                this.resultsTextBox.Text = state.Pi;
                this.calcToolStripProgressBar.Maximum = state.TotalDigits;
                this.calcToolStripProgressBar.Value = state.DigitsSoFar;
            }
            catch (Exception e)
            {
                Console.WriteLine("{0} in ShowProgressState", e.Message);
                throw e;
            }
        }

Create a method with return type Task that encapsulates the work. In order to report progress, create an Progress delegate with an Action that reports progress. CalcPiWithProgress is CPU-bound, so call it with Task.Run. The async keyword in the signature means that await is a keyword in the body of the method.

        async Task DoWork()
        {
            //Any method that is an Action, has one parameter of the gerenic type and returns void.
            Action actionProgress = ShowProgressState;
            //The Action and the Progress must have the same generic type.
            IProgress progress = new Progress(actionProgress);
            await Task.Run(() => CalcPiWithProgress(
                  (int)this.decimalPlacesNumericUpDown.Value, progress)
                );

        }


Start task. The await keyword causes the method to start asynchronously. When the thread completes, the code after the await will be run in the same thread context. The handler does not block: SetUIReady is called, but only after the thread completes, and well after the handler completes.

        async void calcButton_Click(object sender, EventArgs e)
        {
            SetUIBusy();

            // Begin calculating pi asynchronously
            await DoWork();

            SetUIReady();
        }

A special method is not needed to catch the completion of the thread, as with a background worker.

Modify the CalcPi method so it reports progress.

    void CalcPiWithProgress(int digits, IProgress progress,) {
      StringBuilder pi = new StringBuilder("3", digits + 2);

      CalcPiUserState state = new CalcPiUserState(pi.ToString(), digits, 0);
      // Report initial progress
      if (progress != null)
                progress.Report(state);

      if( digits > 0 ) {
        pi.Append(".");

        for( int i = 0; i < digits; i += 9 ) {
          int nineDigits = NineDigitsOfPi.StartingAt(i + 1);
          int digitCount = Math.Min(digits - i, 9);
          string ds = string.Format("{0:D9}", nineDigits);
          pi.Append(ds.Substring(0, digitCount));

          // Report continuing progress
          state = new CalcPiUserState(pi.ToString(), digits, i + digitCount);
          if (progress != null)
                progress.Report(state);  
        }
      }
    }

Catch Exceptions

Background Worker

Test the Error property in the RunWorkerCompletedEventArgs in the RunWorkerCompleted handler.

void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
  
      SetUIReady();

      // Was there an error?
      if( e.Error != null ) {
        this.resultsTextBox.Text = e.Error.Message;
        return;
      }

    }

Task 

With Task, the code after the await is run on the UI thread. The code after the await is executed after the thread completes. The handler would have completed long ago.

Catch the exception and reset the UI.

        async void calcButton_Click(object sender, EventArgs e)
        {
            try
            {
                SetUIBusy();

                // Begin calculating pi asynchronously
                await DoWork();

            }
            catch (Exception ex)
            {
                this.resultsTextBox.Text = ex.Message;
            }
            finally
            {
                SetUIReady();
            }
        }

Return a Result from the Thread 

Background Worker

Set the result of the thread in the DoWorkEventArgs in the DoWork handler.

  void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) { 
      // Track start time
      DateTime start = DateTime.Now;

      CalcPi((int)e.Argument);     

      // Return elapsed time
      DateTime end = DateTime.Now;
      TimeSpan elapsed = end - start;
      e.Result = elapsed;
  }

Retrieve the result from the RunWorkerCompletedEventArgs in the RunWorkerCompleted handler.

void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
  
      SetUIReady();

      // e.Result will cause an error if the thread threw an exception
      if( e.Error != null ) {
        this.resultsTextBox.Text = e.Error.Message;
        return;
      }

      // Show elapsed time
      TimeSpan elapsed = (TimeSpan) e.Result;
      MessageBox.Show("Elapsed: " + elapsed.ToString());
}

Task 

Instead of using Task, use Task. The async command  changes the meaning of the method signature. It does not mean that the method returns Task, it means that the method has a call to await and returns type T.

        async Task DoWork()
        {
            // Track start time
            DateTime start = DateTime.Now;

            //Any method that is an Action, has one parameter of the gerenic type and returns void.
            Action actionProgress = ShowProgressState;
            //The Action and the Progress must have the same generic type.
            IProgress progress = new Progress(actionProgress);
            await Task.Run(() => CalcPiWithProgress(
                  (int)this.decimalPlacesNumericUpDown.Value, progress)
                );

            // Return elapsed time
            DateTime end = DateTime.Now;
            TimeSpan elapsed = end - start;
            return elapsed;
        }


The result will be assigned from the await command.

        async void calcButton_Click(object sender, EventArgs e)
        {
            try
            {
                SetUIBusy();

                // Begin calculating pi asynchronously
                TimeSpan elapsed = await DoWork();

                // Show elapsed time
                MessageBox.Show("Elapsed: " + elapsed.ToString());

            }
            catch (Exception ex)
            {
                this.resultsTextBox.Text = ex.Message;
            }
            finally
            {
                SetUIReady();
            }
        }

Adding the Ability to Cancel

Background Worker


Set the WorkerSupportsCancellation property

Signal that the thread should stop.

void calcButton_Click(object sender, EventArgs e) {
      // Don't process if cancel request pending
      // (Should not be called, since we disabled the button...)
      if( this.backgroundWorker.CancellationPending ) { return; }

      // If worker thread currently executing, cancel it
      if( this.backgroundWorker.IsBusy ) {
        this.calcButton.Enabled = false;
        this.backgroundWorker.CancelAsync();
        return;
      }

      SetUIBusy();

      // Begin calculating pi asynchronously
      this.backgroundWorker.RunWorkerAsync(
        (int)this.decimalPlacesNumericUpDown.Value);
    }

The thread monitors the flag for cancellation. When requested, the thread stops working.

  void CalcPi(int digits)
  {
      StringBuilder pi = new StringBuilder("3", digits + 2);

      CalcPiUserState state = new CalcPiUserState(pi.ToString(), digits, 0);
      // Report initial progress
      this.backgroundWorker.ReportProgress(0, state);

      // Check for cancelation
      if (this.backgroundWorker.CancellationPending) { return; }

      if( digits > 0 ) {
        pi.Append(".");

        for( int i = 0; i < digits; i += 9 ) {
          int nineDigits = NineDigitsOfPi.StartingAt(i + 1);
          int digitCount = Math.Min(digits - i, 9);
          string ds = string.Format("{0:D9}", nineDigits);
          pi.Append(ds.Substring(0, digitCount));

          // Report continuing progress
          state = new CalcPiUserState(pi.ToString(), digits, i + digitCount);
          this.backgroundWorker.ReportProgress(0, state);

          // Check for cancelation
          if (this.backgroundWorker.CancellationPending) { return; }         
        }
      }
    }

In the RunWorkerCompleted handler check the Cancelled property in the event args.

void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
      // Reset progress UI
      this.calcButton.Text = "Calculate";
      this.calcButton.Enabled = true;
      this.calcToolStripStatusLabel.Text = "Ready";
      this.calcToolStripProgressBar.Visible = false;

      // Was the worker thread cancelled?
      if (e.Cancelled)
      {
          this.resultsTextBox.Text = "Cancelled";
      }
      else
      {
          // Show elapsed time
          TimeSpan elapsed = (TimeSpan)e.Result;
          MessageBox.Show("Elapsed: " + elapsed.ToString());
      }

Task


As the thread is asked to respond in more ways, it is useful separate the actions performed when the thread ends. As part of the Task class, use the Continue with to specify a method that has the format for Action. Action, Func and Func can also be configured. If the UI will be accessed, then continue from the current context.

        async void calcButton_Click(object sender, EventArgs e)
        {

            SetUIBusy();

            // Begin calculating pi asynchronously
            await DoWork().ContinueWith(WorkCompleted,
                TaskScheduler.FromCurrentSynchronizationContext());

        }




Many states of the task can be inspected. This version does the same as the earlier version of the application. Next, cancellation will be added.

        private void WorkCompleted(Task task)
        {
            switch (task.Status)
            {
                case TaskStatus.Canceled:
                    break;
                case TaskStatus.Faulted:
                    this.resultsTextBox.Text = task.Exception.ToString();
                    break;
                case TaskStatus.RanToCompletion:
                    MessageBox.Show("Elapsed: " + task.Result.ToString());
                    break;
                default:
                    break;
            }
            SetUIReady();
        }


For cancellation, CancellationTaskSource is used. It contains a token that can be set. The token can be monitored by the thread.

        CancellationTokenSource tokenSource;
        CancellationToken token;

        public MainForm() {
            InitializeComponent();
            tokenSource = new CancellationTokenSource();
            token = tokenSource.Token;
            SetUIReady();
        }

A new helper will be added to report progress and check for cancellation, with the ThrowIfCancellationRequested() method of the token.

        void ProgressTestCancel(
            IProgress progress, CancellationToken token, CalcPiUserState state)
        {
            // Report progress
            if (progress != null)
                progress.Report(state);
            token.ThrowIfCancellationRequested();    
        }


The worker thread reports progress and tests for cancellation at regular intervals.

    void CalcPiWithProgress(
          int digits, IProgress progress, CancellationToken token) 
   {
      StringBuilder pi = new StringBuilder("3", digits + 2);

      CalcPiUserState state = new CalcPiUserState(pi.ToString(), digits, 0);
      // Report initial progress
      ProgessTestCancel(progess, token, state);

      if( digits > 0 ) {
        pi.Append(".");

        for( int i = 0; i < digits; i += 9 ) {
          int nineDigits = NineDigitsOfPi.StartingAt(i + 1);
          int digitCount = Math.Min(digits - i, 9);
          string ds = string.Format("{0:D9}", nineDigits);
          pi.Append(ds.Substring(0, digitCount));

          // Report continuing progress
          state = new CalcPiUserState(pi.ToString(), digits, i + digitCount);
          ProgessTestCancel(progess, token, state); 
        }
      }
    }

Pass the token into the method that does the asynchronous work. The task will be needed in other parts of the application to improve the interaction of the UI, so the task is added as an instance variable. Does this remind you of background worker???

         //Needed in order to test if Task is busy in other methods
        Task piTask = null;
        async Task DoWork()
        {
            // Track start time
            DateTime start = DateTime.Now;

            //Any method that is an Action, has one parameter of the gerenic type and returns void.
            Action actionProgress = ShowProgressState;
            //The Action and the Progress must have the same generic type.
            IProgress progress = new Progress(actionProgress);
            piTask = new Task(() =>
                 TimePiThread(
                    (int)this.decimalPlacesNumericUpDown.Value, progress, tokenSource.Token)
                 , tokenSource.Token);
            piTask.Start();
            return await piTask;
         
        }


The button handler will have two possible states: ready to run, ready to cancel. Update the UI based on the state of the task. If the task is running, cancel it on click.

        async void calcButton_Click(object sender, EventArgs e)
        {
            // Don't process if cancel request pending
            // Should not happen, since button will be disabled
            if (this.tokenSource.IsCancellationRequested) { return; }

            if (piTask != null && !piTask.IsCompleted)
            {
                this.calcButton.Enabled = false;
                tokenSource.Cancel();
            }
            else
            {

                SetUIBusy();

                // Begin calculating pi asynchronously
                await DoWork().ContinueWith(WorkCompleted,
                    TaskScheduler.FromCurrentSynchronizationContext());
            }

        }

The helpers for updating the UI need modification, too:

        void SetUIReady()
        {
            // Reset progress UI
            this.calcToolStripStatusLabel.Text = "Ready";
            this.calcToolStripProgressBar.Visible = false;
            this.calcButton.Text = "Calculate";
            this.calcButton.Enabled = true;
        }

        void SetUIBusy()
        {
            // Set calculating UI
            this.calcToolStripProgressBar.Visible = true;
            this.calcButton.Text = "Cancel";
            this.calcToolStripStatusLabel.Text = "Calculating...";
        }

Conclusion

For updating the UI, I still like background worker. In large part, this is due to my understanding of background worker. Task is new to me. It has more power than background worker for other tasks, but background worker is tailored for interacting with the UI. While writing this article, I was frustrated multiple times with the syntax of lambda functions and the .NET delegates. Background worker hides the details, but allows all the necessary features for interacting with the UI.

Wednesday, September 14, 2016

Using GitHub for Homework Submissions

I teach a course in Windows programming. I use Visual Studio. All programming projects are team projects. I have eight teams, with a repository for each team.

Each group in my class has four or five students. Four seems to be the best number, since it is harder to arrange a meeting for five people. For each group, I created a team in GitHub.

Each student must create a GitHub account and send it to me, then I invite them to the team.

I created eight private repositories in GitHub, so only an authorized team has access. The repository is for all the homework assignments. Each repository has one team assigned to it.

The master branch in the repository only has a README file. The file indicates that each homework assignment will be in a separate branch. I populate the branch with a Visual Studio solution.

Once the student, X, has accepted the invitation to the team, X will be able to view the repository in GitHub. The repository has a button for "Clone or Download". Clone is the preferred method. The URL to use to clone the repository is displayed. X should copy the URL and open Visual Studio.

In Visual Studio, X should open Team Explorer. Look for the icon that looks like a plug. It is for Connections. Open it and look under Local Git Repositories. Click the Clone drop-down indicator. Paste the URL from GitHub and click Clone.

After the repository has been downloaded, click the Home icon to go the home screen. On the home screen, click the Branches link. Near the bottom of the screen are the Active Git Repositories. Open the remotes/origin link. Select the branch for the current homework.

Once the correct branch is selected, return to the Home screen. At the bottom, under solutions, should be the homework solution. Double click it and the solution files will be opened in Visual Studio. Open Solution Explorer and start modifying the file.

After making edits, return to Team Explorer and select Changes. Commit All the changes and Push at the same time.

Before starting a new editing session, open Team Explorer, select the solution, and Sync to the remote server.

To populate with an existing solution,
In GitHub,
  1. Create a branch for the assignment in the repo on GitHub
In VS,
  1. Create a new local repo. 
  2. In the local repo settings, set the remote address to the clone address for the remote repo.
  3. Return to Home and select Sync
  4. Perform a fetch to get the hw branch.

The Open solution option in the local repo will only work if the repo is empty. To circumvent,
  1. Open File Explorer and navigate to the repo folder. 
  2. Copy the initial folder that contains the solution into the folder.

Back in VS, the solution will now appear in the local repo.
  1. From Home, select Changes and Commit and Push to commit the .git files
  2. Double-click the solution to open it.
  3. From Home, select Changes and Commit and Push to commit the .git files

Later, I wanted to update the repository with the next version of the submitted homework, since not all students chose to use the repository. Many changes had been made since the initial contents.

I created a branch in GitHub for me from the initial state and sync'd it in VS. Then I opened the new solution in VS. From Home I viewed Changes and committed and pushed to GitHub. In GitHub, I performed a pull request into the original branch from the new branch. No conflicts were present, so the merge was possible. 

Monday, August 29, 2016

Yii User Setting isAdmin

The Yii framework has CUserIdentity as the basis for logging into an application.

It is possible to add state to the class, so an identity can be tested easily; for example, testing if a menu option should displayed for the current user.

array(
    'label'=>'List OfficeVisit', 
    'url'=>array('index'), 
    'visible'=>yii::app()->user->isAdmin)

The CUserIdentity class has support for adding state with setState. The state can be retrieved with getState, or by accessing the state directly as a property.

In the UserIdentity class in the application, which extends CUserIdentity, add the following in the authenticate method, after authenticating:

if ($this->username==='dbadmin') {
     $this->setState('isAdmin', true);

}

The state can be accessed later with either:

yii::app()->user->getState('isAdmin')

or

yii::app()->user->isAdmin

Refer to http://www.yiiframework.com/wiki/6/how-to-add-more-information-to-yii-app-user/ for more information.

 

More Blogs

Followers