Jon Rumsey

An online markdown blog and knowledge repository.


Project maintained by nojronatron Hosted on GitHub Pages — Theme by mattgraham

Week 7 Class Notes

Monday 27 June Notes

Upcoming

Technical interviewing in 2 weeks, which will over prep us for most real interviews.

Continuation of Android dev using the Task Master app.

Using Rooms: Is an ORM (Object Relational Manager) + SQL Queries.

AWS Amplify on Tuesday and DynamoDB => AWS is a high-value skill set.

Advice:

TCP/IP and REST are common networking / WRRC techniques, regardless of the framework or language used.

Graphs: Not on final technical whiteboard. Abstract datastructure that things data together with 'paths'.

Rooms

Room Database: Similar to the 3-liner JPA Code in Spring, but we will need to build our own Queries.

The App talks to the Room DB, and in parallel communities with the DAO (Data Access Object).

The DAO does "get entities", and persists data back to the DB.

Entities is the same as before, Classes with annotations and GET/SETters.

Emulator Requirement: Must set the phone Emulator API to (32?).

See Android Developer Docs

Database Inspector:

SQL Lite:

Data Access Object:

Rooms Setup:

Create Entities to model the data:

Create an ENUM if one is necessary:

// package reference here
public enum EnumName { 
  CATEGORY1("category1"), 
  CATEGORY2("category2"); 
  private final String someString; 
  // CTOR
  // getters, setters
  // @Override toString() or other overrides and custom methods as necessary
  }

Implement the Enum in the entity:

Adding Entity Decorators:

Create a DAO for the Entities:

  1. Create a DAO interface to represent Entity/Entities.
  2. import packages: androidx.room.?: Dao, Insert, Query
  3. Decorate the class with @Dao
  4. Decorate a create method with @Insert: @Insert public void insertEntity(Entity entity);
  5. Decorate a FindAll method with @Query: @Query("SELECT * FROM Entity ORDER BY field ASC") public List<Product> findAll();
  6. Decorate a FindByAnId method with @Query: @Query("SELECT * FROM Entity WHERE id = :id") public Entity findById(Long id);

An DAO can use GENERICS!

Create a Database Representation:

  1. Create a Database Package.
  2. Create a public Abstract Class named appropriately because it should not be instantiated.
  3. Extend RoomDatabase object (see docs).
  4. Add '@Database(entities={class1},{class2},{...etc}, version=1') annotation to the abstract class declaration. This will tell the DB what Tables it needs.
  5. INSIDE THIS CLASS add the DAO by creating an abstract method: public abstract EntityDao entityDao();

Create DB Converters Class:

  1. Add this new class to the database Package.
  2. This will be a public class.
  3. Use '@TypeConverter' annotation above the methods (see code snippet example below).
  4. Create a method to go back-and-forth between the conversion types.
// this converts timestamp to date
@TypeConverter
public static Date fromTimeStamp(Long value) {
  return value == null ? null : new Date(value);
}

// this converts date to timestamp
@TypeConverter
public static Long dateToTimestamp(Date date) {
  return date == null ? nul : date.getTime();
}

Create a Database now that the boilerplate DB interface layer code is done!

  1. Set variables to represent the Database DAO as a Field.
  2. Work within the OnCreate() lifecycle method.

Set variables for what will be needed/injected:

Within OnCreate() method on the MainActivity:

  1. Assign new Room methods to the abstract Database Class.
  2. Room.databaseBuilder(// many methods and props and vars here) build-out the database safely.

Threading

In production environment, you must set up multi-threading so that DB queries do not lock the UI.

For this class, we are going to set "AllowMainThreadQueries()" to avoid DB setup and use errors using Rooms.

For AWS Multi-threading will be utilized and will not require AllowMainThreadQueries() at all.

Save and View DB Items

Once you reach a point where you can build and run the app without errors:

  1. Open App Inspection in IntelliJ IDEA.
  2. Open DB Inspector to view Tables.
  3. Open Table by dbl-click to view the data.

Set Up a Spinner Element:

  1. In the AddItemActivity define a set up spinner method (see example snippet below).
  2. Grab a reference to the Spinner element.
  3. Set an Adapter to handle logic of the Spinner element.
  4. Create a new ArrayAdapter<> with context 'this' comma R.layout.simple-spinner-dropdown-item
  5. An array of items must be provided: See the posted class repo code.

Optional: Add the selectable items into you XML Resources, but this is not a scalable solution like Enums can be.

Optional: Use explicit casting "(Spinner)" to ensure ref is captured.

  1. Define a private void method to handle storing a new data item.
  2. Instantiate a Button instance e.g. Save button.
  3. Create a new setUpSaveButton() method to set up Spinner, Button, and set a new onclick Listener.
  4. Create a lambda onClick(View view) Event Listener to:
  5. Find by ID to get name input of the Task (or thing).
  6. Create a new product name and product description based on what was selected.
  7. Apply any new data to local variables.
  8. Call the Product CTOR and fill it in!
  9. Remember to inject the database Field into this method so DB operations can be done within it.

Note: When casting to ensure types are correct, use parenthesis to enforce order-of-operations - likely you are trying to write multi-line statements onto a single line.

Enum Notes: Define it as a child to the class that needs it, and include toString() and fromString() methods to ensure it can be called.

Tracking Element IDs: Use the XML to more rapidly find and copy/past IDs, rather than the rendered UI.

Required: You must get a reference to the Spinner UI element in order to do anything with it.

Snackbar

Belayed until another time.

OnResume

Remember anything you put into OnCreate()? Those are stuck in the Lifecycle.

Use super.onResume(); and add use clearn() and getAllItem() etc to load the Fields on subsequent times the Activity is loaded.

Tell RecyclerView that data has changed behind it without the Adapter being scoped to the Class level e.g. ProductListRecyclerViewAdpater plrvAdapter; and then use that Field within Class.methods().

Expectations for Today

Code Challenge: Time box to no more than 2 hours! (me):

Lab 29: Room => Task Model and Room, Add Task Form, updates to Home and Details pages. Stretch goals (2, optional).

Tuesday Morning

All AWS, today and tomorrow.

Host mobile apps using AWS Amplify.

Insertion Sort Whiteboard Review

When you write "Edge Case" on your technical whiteboard, think of it like this: "What are the 'edges' of the data/inputs and outputs that my function has to deal with?"

Always good to include a step-through.

Use colors to identify areas of a step-through such as iterations the step-through step is in.

Remember to add test-case handling in your pseudocode.

Merge-Sort Code Challenge

Make sure you whiteboard this! Even if coding doesn't happen, have a whiteboard ready for Weds morning discussion.

AWS Amplify Part 1

There are dozens of AWS Cloud Services, many devs know 1, we will have experience with 4 by the time we graduate.

AWS is a collection of APIs and platforms to provide services.

SNS: Automate (or manual) message-sending service.

Elastic Beanstalk: Like Heroku but charges money.

Can create a budged in the Billing Console > Budgets window, and make sure it applies to all AWS Services.

Note: A budget and alerts in AWS Billing Console has been set up!

Remove ROOM

  1. build.gradle: Remove ROOM references.
  2. Remove TaskManager Database class: Say yes to removing the references.
  3. Delete the DAO Class implementation (TasksDao.java).
  4. Model: Remove '@entity' and primary key annotations from the model class(es).
  5. Enter each Activity and remove references to Database Variables.
  6. It might be necessary to refactor some custom methods in order to remove the database references completely, so comment-out code and leave TODOs for what needs to be revisited.
  7. The TypeConverter might have a problem because it was annotated along with the DB and Room stuff.
  8. Consider doing an Emulator "Wipe" command by closing the Emulator and selecing the 'Wipe Data' menu item in the emulated phone's entry in the Device Manager.

AWS Amplify Management CLI

Read the docs on how to download and install

Commands:

Create an IAM User
  1. Logon as Root user.
  2. Open the Identity and Access Management view > Users
  3. Download the AWS Amplify CLI

Note: AdministrativeAccess-Amplify is selected by default, DE-SELECT IT and just select AdministrativeAccess.

Note: DOWNLOAD the CSV of the newly created users. This will be necessary in the AWS CLI console when logging in.

Setup AWS Amplify on TaskManager

Update build.gradle scripts at the Project level and the App level to support AWS Amplify.

The AWS Amplify getting started document has a list of items that must be added to the Project's build.gradle.

GraphQL

Checkout the graphql.org Learn Files

GraphQL notes:

Lambdas

Detects specific ACTIONS, and perform processing when the Action occurs.

Tuesday Assignments

Wednesday 29-June

Is Data CIA? Stored Confidentiality, with Integrity, and Available?

Cloud Pros:

CLoud Cons:

Integrating AWS With Android App

After installing Amplify, additional folders are put in your Project.

GraphQL will also add folder and files including a Schema json, queries, etc.

step to convert from Room to Amplify w/ GraphQL:

  1. deleted db and daos
  2. delete your model
  3. remove all annotations and imports from your files
  4. add amplify dependinces into gradle
  5. add atskmasteramplifyapplication to extend app
  6. put amplify config into above app file
  7. update graphql schema (then api update on cli, after success then push w/o conflict resolution)
  8. run amplify codefen models to generate them locally
  9. delete old model and convert every usage in your app
  10. every dao usage needs to be converted to aplify api usage
  11. change recyclerviewadapter to have better string output

From Instructor Alex:

  // Steps for adding Amplify to your app
  // 1. Remove Room from your app
  //   1A. Delete the Gradle Room dependencies in app's (lower-level) build.gradle
  //   1B. Delete database class
  //   1C. Delete DAO class
  //   1D. Remove `@Entity` and `@PrimaryKey` annotations from the Product model class
  //   1E: Delete the database variables and instantiation from each Activity that uses them
  //   1F: Comment out DAO usages in each Activity that uses them
  // 2. Make an IAM user
  // 3. Run `amplify configure`
  // 4. Add Amplify Gradle dependencies in build.gradle files
  // 5. Run `amplify init`
  // 6. Run `amplify add api` (or `amplify update api`)
  // 7. Run `amplify push`
  // 8. Change model in "amplify/backend/api/amplifyDatasource/schema.graphql" to match your app's model
  // 9. Run `amplify api update` -> Disable conflict resolution
  // 10. Run `amplify push --allow-destructive-graphql-schema-updates`
  // 11. Run `amplify codegen models`
  // 12A. Add an application class that extends Application and configures Amplify
  // 12B. Put the application class name in your AndroidManifest.xml
  // 12C. Uninstall the app on your emulator
  // 13. Convert every usage of model classes to use Amplify generated models in app/src/main/java/com/amplifyframework/datastore/generated/model
  //   13A. Instantiate classes using builder
  //   13B. Get data elements via getters (if you aren't already)
  // 14. Convert all DAO usages to Amplify.API calls
  // 15. Update RecyclerView adapter's collection via runOnUiThread()
  // 16. Fix date output in RecyclerView items

Wednesday Lab

Add Task Form, refactor your homepage recyclerview, and get Amplify up and running.

Remove Enum from the project, add a hard-coded list of Strings that represent all the categories.

Spinner code might have to be altered to utilize the list instead.

Remember to utilize onResume property to ensure re-vising views are updated with Amplify + Dynamo latest data.

Code Challenge Quick Sort

No deductions for late submissions.

Most complex of all sort algorithms.

JS Array.sort() uses Quicksort.

Quicksort is a common interview question.

Thursday June-30

AWS and Billing:

Quicksort Whiteboard Review and Comments

Final Technical Whiteboard and Interviews will require camera on.

Put your working screen under the camera so your face is head-on with the camera feed.

Pivot:

Managing Quicksort Temporary Placeholders:

Variable LOW is used to track how many values are less than the PIVOT point.

Relational Data in GraphQL

One => Many and Many => One

Note: Many to Many is a Left-Join SQL in the end.

Use the schema.graphql file to build new table(s).

Create a new 'type', name it, and utilize directives '@model', '@auth' etc.

type Contact @model @auth(rules: [{allow:public}]) {
  id: ID!
  email: String!
  fullName: String
  products: [Product] @hasMany(indexName: "byContact", fields: ["id"])
}

Update Product to enable the FK relationship:

type Product @model @auth(rules: [{allow:public}]) {
  id: ID!
  name: String!
  description: String
  dataCreate: AWSDateTime
  productCategory: String
  contactId: ID! @index(name: "byContact", sortKeyFields: ["name"])
  contactPerson: Contact @belongsTo(fields: ["contactId"])
}

Note: Relationship descriptions API has been updated a little, is similar, but a lot cleaner.

When done editing Schema:

  1. Update CodeGenModels 'amplify codegen models' in Amplify CLI.
  2. Run 'amplify status' in the CLI.
  3. Run 'amplify push' and answer the quesions according to your app requirements.
  4. View the results in Amplify Admin UI after the PUSH operation completes.

When creating a new entity (Amplify Class) after setting up the schema:

  1. Assign a variable of type that is the name of the Schema model.
  2. The value will be a ModelName.buildeer() with chained commands that set the Fields, rather than using a CTOR.
  3. Call Amplify.API.mutate() with args and callback handlers to call ModelMutation.create(variable_created_in_first_step).
// sample code from Taskmaster project
Task task = Task.builder()
  .title(newTaskTitle)
  .body(newTaskDescription)
  .state(newTaskStatus)
  .build();

Amplify uses 'success' as a callback function.

Inside an Amplify success callback add:

// sample code from Taskmaster project
Log.i("", "Entered incrementTaskCounter lambda.");
TextView successText = AddTask.this.findViewById(R.id.submittedText);

// aws amplify graphql insert method
Amplify.API.mutate(
  ModelMutation.create(teamAlpha),
  response -> Log.i("HomeActivity", "Added Team with id: " + response.getData().getId()),
  error -> Log.e("HomeActivity", "Failed to create new Team", error)
);

finish(); // necessary to exit the lambda

Note: Review ApiModelname.java to see what the params are needed for Queries and Scaler methods!!

Grabbing a stream of a collection and filter it for a selected item (comparisonObj) and return it as an instance, else throw a specific exception:

myModel.stream().filter(c -> c.getter().equals(comparisonObj)).findAny().orElseThrow(RuntimeException::new);

Completable Future

Similar to JS Promises, which are asynchronous methods.

Asynchronous is not procedural programming.

Asynchronous will take whatever time the longest call takes.

Synchronous will take the SUM OF ALL CALLS in order.

CompletableFuture is an asynchronous package.

CompletableFuture<List<MyModel>> thingFuture = null;

Closing methods are necesary: To resolve the CompletableFuture (e.g. tell it to complete) you must include '.complete(arg)'.

You must complete a CompletableFuture otherwise your app will hang, so Exceptions must be handled.

CompletableFuture Exceptions receive 2 params, the output (if processing completed) and the exception that was thrown.

To capture the exception write the 3rd parameter like:

failure -> {
  mymodelFuture.complete(null);
  Log.e(String logTitle, String customMessage);
}

Another CompletableFuture exception type: InterruptedException.

Note: You might run into a 'null reference exception' when using CompletableFuture calls. How to deal with this? TBD

Thursday Lab

Advice:

Thursday Partnered Code Challenge

MUST BE PAIRED.

Treat as if this is the final technical interview.

Other AWS Services

Cognito

DynamoDB

S3

Friday Class Notes

Career Coaching Workshop

  1. Graduate!
  2. Targeted Job Search.
  3. Stellar Resume.
  4. Informational/Recruitment Call. You might be asked for your target salary range.
  5. On-site Interview. Tell me about yourself? Elevator pitch! Remain calm so knowledge access is possible.
  6. Receive an offer! Prepare to decide whether to walk-away or how to accept.
  7. Negotiation => Job Offer!

Technical Spruce-up

GitHub:

Tools and Online Editors for Collaborating and Proving

Graphs

These notes supplement reading notes on graphs in this repo.

Lots of examples of Graphs, generally, in the world.

Graph are interconnected data structures.

Nodes in Graphs are called Vertices.

Note: Try to stick with the accepted terminology so everyone is on the same page especially Vertices vs Nodes.

Root: The starting vertex when analysing and traversing a graph.

Potential Connections: Edges are connections, and Graphs have neighbors via edges. But not all Vertices are connected directly to all others.

Neighbor: Currently-adjacent Vertex.

Degree: Number of edges connected to a Vertex.

Traversals:

Cyclic vs Acyclic:

Edges can have Weight:

Code Challenge for Friday

Graph Implementation!

Remember left and right? These are edges!

Reference all edges like done in the kAry Tree!

Find vertices via Breadth First Traversal and return the collection.

Consider using a hashset or set to track visited vertices.

References

Wikipedia article Amazon Web Services

Pseudocode Reference from CSC Calpoly Institute

TODOs

[ ] TaskMaster: How to alter the background colors on Activities.

[ ] Android Studio: Create a macro to do common things like: Font resize/zoom.

Return to Root README.md