SlideShare a Scribd company logo
Creating a Netflix Clone
III
In the 3rd part we’ll dive right into the model objects representing the server and ultimately the front end code. If you’re unfamiliar with entities, JPA, UUID etc. I suggest
going back to the previous modules and refreshing your memory a bit as we’ll build a lot on top of that.

One way in which this will be different though is the usage of Lombok which will make the code far more terse.

Still the code here is mostly mock. The real world Netflix has a lot of code but most of it applies to algorithmic scheduling, user management, scaling etc. All of these
aren’t applicable here.

In this lesson our focus will be on entities and Data Transfer Objects also known as DTOs which I sometimes mixed with data access objects or DAO. There is overlap
between both of those concepts but what we have is generally DTOs as they transfer data to the client. They don’t just abstract the database layer.
codenameone.com github.com/codenameone/CodenameOne
Server Internals
In the 3rd part we’ll dive right into the model objects representing the server and ultimately the front end code. If you’re unfamiliar with entities, JPA, UUID etc. I suggest
going back to the previous modules and refreshing your memory a bit as we’ll build a lot on top of that.

One way in which this will be different though is the usage of Lombok which will make the code far more terse.

Still the code here is mostly mock. The real world Netflix has a lot of code but most of it applies to algorithmic scheduling, user management, scaling etc. All of these
aren’t applicable here.

In this lesson our focus will be on entities and Data Transfer Objects also known as DTOs which I sometimes mixed with data access objects or DAO. There is overlap
between both of those concepts but what we have is generally DTOs as they transfer data to the client. They don’t just abstract the database layer.
codenameone.com github.com/codenameone/CodenameOne
Server Internals
Now that we know Lombok basics we can move on to the server
The code is mostly mock code
We’ll start with the entity model code first
In the 3rd part we’ll dive right into the model objects representing the server and ultimately the front end code. If you’re unfamiliar with entities, JPA, UUID etc. I suggest
going back to the previous modules and refreshing your memory a bit as we’ll build a lot on top of that.

One way in which this will be different though is the usage of Lombok which will make the code far more terse.

Still the code here is mostly mock. The real world Netflix has a lot of code but most of it applies to algorithmic scheduling, user management, scaling etc. All of these
aren’t applicable here.

In this lesson our focus will be on entities and Data Transfer Objects also known as DTOs which I sometimes mixed with data access objects or DAO. There is overlap
between both of those concepts but what we have is generally DTOs as they transfer data to the client. They don’t just abstract the database layer.
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Content {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private UUID id;
private String name;
private String description;
@OneToOne
private Media heroImage;
@OneToOne
private Media icon;
@OneToOne
private Media logo;
@ManyToMany
private Set<Media> videos;
public ContentDTO getDTO() {
Map<VideoQuality, String> qualityUrls = videos.stream().
collect(Collectors.
Source Listing - Content
codenameone.com github.com/codenameone/CodenameOne
Writing an entity with Lombok is much easier. There are no, getters, setters, constructors, equals, hash code etc. Notice we still use JPA just like we used to so we have
the JPA entity annotation and then the Lombok annotations.
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Content {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private UUID id;
private String name;
private String description;
@OneToOne
private Media heroImage;
@OneToOne
private Media icon;
@OneToOne
private Media logo;
@ManyToMany
private Set<Media> videos;
public ContentDTO getDTO() {
Map<VideoQuality, String> qualityUrls = videos.stream().
collect(Collectors.
Source Listing - Content
codenameone.com github.com/codenameone/CodenameOne
Everything works as you would expect including the primary key definition etc. Notice I chose to go with a UUID object as a primary key coupled with auto-generation.
That’s a much simpler trick than the one I picked in previous modules.
codenameone.com github.com/codenameone/CodenameOne
UUID Keys
Strings as keys are important, they eliminate scanning attacks
JPA lets us use the UUID class and the rest is pretty much seamless
This could be costly for RDBMS inserts
Unless you’re doing millions of inserts this shouldn’t be a problem
We already talked about using strings for keys. When we use a UUID object we get a long string that isn’t guessable in the database. That means that we can expose
that primary key to the end user without worrying that he might use it to scan through details of other users as the string is pretty long and hard to guess.

As we saw, we just need to use the UUID object type. There are several other strategies for generating a UUID in JPA. I chose the simplest one, it might not be the best
one but it is convenient.

So why doesn’t everyone use this approach?

Turns out it’s much slower than using numeric auto-increment values on a database column. DB’s such as MySQL are heavily optimised for auto-increment fields and
String based primary keys are just slower to insert. Some developers consider that a non-starter especially when looking at the performance graph which is “scary”.
Performance really takes a dive for insert operations while it remains flat when using long auto-increment fields.

Personally I don’t think that’s a problem even for a video app like this. You wouldn’t insert too often and read operations are still pretty fast. This might become an issue if
you have a log or auditing table that might include multiple insert operations per second. At that point you’d need to use a long for the primary key and make sure never
to expose it externally.
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Content {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private UUID id;
private String name;
private String description;
@OneToOne
private Media heroImage;
@OneToOne
private Media icon;
@OneToOne
private Media logo;
@ManyToMany
private Set<Media> videos;
public ContentDTO getDTO() {
Map<VideoQuality, String> qualityUrls = videos.stream().
collect(Collectors.
toMap(Media::getQuality,
Media::getMediaURL));
return new ContentDTO(id.toString(),
Source Listing - Content
codenameone.com github.com/codenameone/CodenameOne
The name and description fields correspond to these fields in the database. This is the entire definition as the accessors are generated automatically
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Content {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private UUID id;
private String name;
private String description;
@OneToOne
private Media heroImage;
@OneToOne
private Media icon;
@OneToOne
private Media logo;
@ManyToMany
private Set<Media> videos;
public ContentDTO getDTO() {
Map<VideoQuality, String> qualityUrls = videos.stream().
collect(Collectors.
toMap(Media::getQuality,
Media::getMediaURL));
return new ContentDTO(id.toString(),
name, description,
getMedia(heroImage), getMedia(icon),
getMedia(logo), qualityUrls);
Source Listing - Content
codenameone.com github.com/codenameone/CodenameOne
We have three one to one media relations. These include the three images for every content item. Specifically:

- The hero image which is the big picture that appears on top of the application

- The show logo is displayed on top of the hero image. It’s a separate image to support different device aspect ratio and layout

- The icon is the image representing a show within the list
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Content {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private UUID id;
private String name;
private String description;
@OneToOne
private Media heroImage;
@OneToOne
private Media icon;
@OneToOne
private Media logo;
@ManyToMany
private Set<Media> videos;
public ContentDTO getDTO() {
Map<VideoQuality, String> qualityUrls = videos.stream().
collect(Collectors.
toMap(Media::getQuality,
Media::getMediaURL));
return new ContentDTO(id.toString(),
name, description,
getMedia(heroImage), getMedia(icon),
getMedia(logo), qualityUrls);
Source Listing - Content
codenameone.com github.com/codenameone/CodenameOne
Finally we have the actual video files which we store in media objects as well. We can have multiple video files representing different quality levels of the video. In real life
we can have even more options such as different aspect ratios, languages etc.

Normally I would like this to be a Map between quality and media but this is a bit challenging to represent correctly in JPA so I left this as a simple set.
@OneToOne
private Media heroImage;
@OneToOne
private Media icon;
@OneToOne
private Media logo;
@ManyToMany
private Set<Media> videos;
public ContentDTO getDTO() {
Map<VideoQuality, String> qualityUrls = videos.stream().
collect(Collectors.
toMap(Media::getQuality,
Media::getMediaURL));
return new ContentDTO(id.toString(),
name, description,
getMedia(heroImage), getMedia(icon),
getMedia(logo), qualityUrls);
}
private byte[] getMedia(Media m) {
return m == null ? null : m.getMedia();
}
}
Source Listing - Content
codenameone.com github.com/codenameone/CodenameOne
For convenience we place the DTO creation within the entity object. This code is mostly just the construction but it there’s one block where we convert the media objects
@OneToOne
private Media heroImage;
@OneToOne
private Media icon;
@OneToOne
private Media logo;
@ManyToMany
private Set<Media> videos;
public ContentDTO getDTO() {
Map<VideoQuality, String> qualityUrls = videos.stream().
collect(Collectors.
toMap(Media::getQuality,
Media::getMediaURL));
return new ContentDTO(id.toString(),
name, description,
getMedia(heroImage), getMedia(icon),
getMedia(logo), qualityUrls);
}
private byte[] getMedia(Media m) {
return m == null ? null : m.getMedia();
}
}
Source Listing - Content
codenameone.com github.com/codenameone/CodenameOne
Map<VideoQuality, String> qualityUrls = new HashMap<>();
for (Media video : videos) {
qualityUrls.put(video.getQuality(), video.getMediaURL());
}
In the DTO it makes more sense to hold the media as a map instead of a list or set. So we translate the video to to a map. 

I find the stream syntax a bit obtuse sometimes. This is how it would look with a standard for loop. Essentially for each element we replace the content with a map where
the key is the quality and the value is the media URL.
@OneToOne
private Media heroImage;
@OneToOne
private Media icon;
@OneToOne
private Media logo;
@ManyToMany
private Set<Media> videos;
public ContentDTO getDTO() {
Map<VideoQuality, String> qualityUrls = videos.stream().
collect(Collectors.
toMap(Media::getQuality,
Media::getMediaURL));
return new ContentDTO(id.toString(),
name, description,
getMedia(heroImage), getMedia(icon),
getMedia(logo), qualityUrls);
}
private byte[] getMedia(Media m) {
return m == null ? null : m.getMedia();
}
}
Source Listing - Content
codenameone.com github.com/codenameone/CodenameOne
Once this is done we create a new DTO object with the automatic constructor and return it.
@OneToOne
private Media heroImage;
@OneToOne
private Media icon;
@OneToOne
private Media logo;
@ManyToMany
private Set<Media> videos;
public ContentDTO getDTO() {
Map<VideoQuality, String> qualityUrls = videos.stream().
collect(Collectors.
toMap(Media::getQuality,
Media::getMediaURL));
return new ContentDTO(id.toString(),
name, description,
getMedia(heroImage), getMedia(icon),
getMedia(logo), qualityUrls);
}
private byte[] getMedia(Media m) {
return m == null ? null : m.getMedia();
}
}
Source Listing - Content
codenameone.com github.com/codenameone/CodenameOne
And finally I also added a small helper method to make the code above a bit simpler. So we won’t get a null pointer exception if the media is null.
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ContentDTO {
private String id;
private String name;
private String description;
private byte[] heroImage;
private byte[] icon;
private byte[] logo;
private Map<VideoQuality, String> videoUrls;
}
Source Listing - ContentDTO
codenameone.com github.com/codenameone/CodenameOne
This is the DTO object we just created. Notice it’s super simple and mostly consists of the Lombok annotations.
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ContentDTO {
private String id;
private String name;
private String description;
private byte[] heroImage;
private byte[] icon;
private byte[] logo;
private Map<VideoQuality, String> videoUrls;
}
Source Listing - ContentDTO
codenameone.com github.com/codenameone/CodenameOne
The strings just map directly to the entity. There’s nothing to say here.
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ContentDTO {
private String id;
private String name;
private String description;
private byte[] heroImage;
private byte[] icon;
private byte[] logo;
private Map<VideoQuality, String> videoUrls;
}
Source Listing - ContentDTO
codenameone.com github.com/codenameone/CodenameOne
For the media I chose to include the icons themselves. I could have taken the approach of returning URLs for the media which might have advantages in the future. For
now this is simpler but possibly not as efficient. Using a URL would have had the advantage of caching the data locally for future refreshes. Using the actual icon means
all the data is transferred with one request.
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ContentDTO {
private String id;
private String name;
private String description;
private byte[] heroImage;
private byte[] icon;
private byte[] logo;
private Map<VideoQuality, String> videoUrls;
}
Source Listing - ContentDTO
codenameone.com github.com/codenameone/CodenameOne
This is the map we created for the media items. We already discussed this in the stream part before. It maps between the video quality enum and the string URL.
package com.codename1.demos.netflixclone.model;
public enum VideoQuality {
NONE,
LOW,
MEDIUM,
HIGH
}
Source Listing - VideoQuality
codenameone.com github.com/codenameone/CodenameOne
For the sake of completeness this is the video quality enum. Pretty simple but matches what we need right now.
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Media {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private UUID id;
private String name;
private String mimeType;
private Instant modified;
private long size;
@Lob
@Column(name = "media", columnDefinition="BLOB")
private byte[] media;
private String mediaURL;
private VideoQuality quality;
}
Source Listing - Media
codenameone.com github.com/codenameone/CodenameOne
The media entity is another standard Lombok entity with the standard trimmings.
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Media {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private UUID id;
private String name;
private String mimeType;
private Instant modified;
private long size;
@Lob
@Column(name = "media", columnDefinition="BLOB")
private byte[] media;
private String mediaURL;
private VideoQuality quality;
}
Source Listing - Media
codenameone.com github.com/codenameone/CodenameOne
We use the same UUID primary key generation logic
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Media {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private UUID id;
private String name;
private String mimeType;
private Instant modified;
private long size;
@Lob
@Column(name = "media", columnDefinition="BLOB")
private byte[] media;
private String mediaURL;
private VideoQuality quality;
}
Source Listing - Media
codenameone.com github.com/codenameone/CodenameOne
Rest of the stuff is pretty standard, notice that we store the modified time as an Instant instead of Date. Instant is a Java 8 date/time API class. It represents a timestamp
and is more convenient to use than date.
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Media {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private UUID id;
private String name;
private String mimeType;
private Instant modified;
private long size;
@Lob
@Column(name = "media", columnDefinition="BLOB")
private byte[] media;
private String mediaURL;
private VideoQuality quality;
}
Source Listing - Media
codenameone.com github.com/codenameone/CodenameOne
The media data is stored in blob storage in the database
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Media {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private UUID id;
private String name;
private String mimeType;
private Instant modified;
private long size;
@Lob
@Column(name = "media", columnDefinition="BLOB")
private byte[] media;
private String mediaURL;
private VideoQuality quality;
}
Source Listing - Media
codenameone.com github.com/codenameone/CodenameOne
Finally the URL to the media and the video quality enum are stored as well. That means we can have multiple instances of the same media object for various quality
levels.

One thing I didn’t cover here is the repositories for the entity objects. They’re all empty as we don’t need any finder methods for this specific demo so it’s all pretty trivial.
codenameone.com github.com/codenameone/CodenameOne
Thank You
Thanks for watching I hope you’ll enjoy the rest of the course and find it educational
Thank You
Thanks for watching I hope you’ll enjoy the rest of the course and find it educational
Thanks for watching I hope you’ll enjoy the rest of the course and find it educational

More Related Content

Similar to create-netflix-clone-03-server_transcript.pdf

Spring boot
Spring bootSpring boot
Advanced Web Development
Advanced Web DevelopmentAdvanced Web Development
Advanced Web Development
Robert J. Stein
 
Dao pattern
Dao patternDao pattern
Dao pattern
ciriako
 
Nt1310 Unit 3 Language Analysis
Nt1310 Unit 3 Language AnalysisNt1310 Unit 3 Language Analysis
Nt1310 Unit 3 Language Analysis
Nicole Gomez
 
Intro to Android Programming
Intro to Android ProgrammingIntro to Android Programming
Intro to Android Programming
Peter van der Linden
 
DevSecCon Singapore 2018 - Remove developers’ shameful secrets or simply rem...
DevSecCon Singapore 2018 -  Remove developers’ shameful secrets or simply rem...DevSecCon Singapore 2018 -  Remove developers’ shameful secrets or simply rem...
DevSecCon Singapore 2018 - Remove developers’ shameful secrets or simply rem...
DevSecCon
 
Builiding Modular monoliths that can scale to microservices. JBCNConf 2021
Builiding Modular monoliths that can scale to microservices. JBCNConf 2021Builiding Modular monoliths that can scale to microservices. JBCNConf 2021
Builiding Modular monoliths that can scale to microservices. JBCNConf 2021
David Gómez García
 
Dao example
Dao exampleDao example
Dao example
myrajendra
 
Googleappengineintro 110410190620-phpapp01
Googleappengineintro 110410190620-phpapp01Googleappengineintro 110410190620-phpapp01
Googleappengineintro 110410190620-phpapp01Tony Frame
 
C++ & VISUAL C++
C++ & VISUAL C++ C++ & VISUAL C++
C++ & VISUAL C++
Makaha Rutendo
 
DevSecCon SG 2018 Fabian Presentation Slides
DevSecCon SG 2018 Fabian Presentation SlidesDevSecCon SG 2018 Fabian Presentation Slides
DevSecCon SG 2018 Fabian Presentation Slides
Fab L
 
Jquery dojo slides
Jquery dojo slidesJquery dojo slides
Jquery dojo slideshelenmga
 
Reaching for the Future with Web Components and Polymer
Reaching for the Future with Web Components and PolymerReaching for the Future with Web Components and Polymer
Reaching for the Future with Web Components and Polymer
FITC
 
iOS Course day 2
iOS Course day 2iOS Course day 2
iOS Course day 2
Rich Allen
 
C++ [ principles of object oriented programming ]
C++ [ principles of object oriented programming ]C++ [ principles of object oriented programming ]
C++ [ principles of object oriented programming ]
Rome468
 
DotNetNuke Client API -DragDropAdminModules.pdf
DotNetNuke Client API -DragDropAdminModules.pdfDotNetNuke Client API -DragDropAdminModules.pdf
DotNetNuke Client API -DragDropAdminModules.pdfarunagulla
 
distributing computing
distributing computingdistributing computing
distributing computing
nibiganesh
 
Learning MVC Part 3 Creating MVC Application with EntityFramework
Learning MVC Part 3 Creating MVC Application with EntityFrameworkLearning MVC Part 3 Creating MVC Application with EntityFramework
Learning MVC Part 3 Creating MVC Application with EntityFrameworkAkhil Mittal
 
How Android Architecture Components can Help You Improve Your App’s Design?
How Android Architecture Components can Help You Improve Your App’s Design?How Android Architecture Components can Help You Improve Your App’s Design?
How Android Architecture Components can Help You Improve Your App’s Design?
Paul Cook
 

Similar to create-netflix-clone-03-server_transcript.pdf (20)

Spring boot
Spring bootSpring boot
Spring boot
 
Advanced Web Development
Advanced Web DevelopmentAdvanced Web Development
Advanced Web Development
 
Dao pattern
Dao patternDao pattern
Dao pattern
 
Nt1310 Unit 3 Language Analysis
Nt1310 Unit 3 Language AnalysisNt1310 Unit 3 Language Analysis
Nt1310 Unit 3 Language Analysis
 
Intro to Android Programming
Intro to Android ProgrammingIntro to Android Programming
Intro to Android Programming
 
DevSecCon Singapore 2018 - Remove developers’ shameful secrets or simply rem...
DevSecCon Singapore 2018 -  Remove developers’ shameful secrets or simply rem...DevSecCon Singapore 2018 -  Remove developers’ shameful secrets or simply rem...
DevSecCon Singapore 2018 - Remove developers’ shameful secrets or simply rem...
 
Builiding Modular monoliths that can scale to microservices. JBCNConf 2021
Builiding Modular monoliths that can scale to microservices. JBCNConf 2021Builiding Modular monoliths that can scale to microservices. JBCNConf 2021
Builiding Modular monoliths that can scale to microservices. JBCNConf 2021
 
Dao example
Dao exampleDao example
Dao example
 
Googleappengineintro 110410190620-phpapp01
Googleappengineintro 110410190620-phpapp01Googleappengineintro 110410190620-phpapp01
Googleappengineintro 110410190620-phpapp01
 
C++ & VISUAL C++
C++ & VISUAL C++ C++ & VISUAL C++
C++ & VISUAL C++
 
DevSecCon SG 2018 Fabian Presentation Slides
DevSecCon SG 2018 Fabian Presentation SlidesDevSecCon SG 2018 Fabian Presentation Slides
DevSecCon SG 2018 Fabian Presentation Slides
 
Jquery dojo slides
Jquery dojo slidesJquery dojo slides
Jquery dojo slides
 
Reaching for the Future with Web Components and Polymer
Reaching for the Future with Web Components and PolymerReaching for the Future with Web Components and Polymer
Reaching for the Future with Web Components and Polymer
 
iOS Course day 2
iOS Course day 2iOS Course day 2
iOS Course day 2
 
C++ [ principles of object oriented programming ]
C++ [ principles of object oriented programming ]C++ [ principles of object oriented programming ]
C++ [ principles of object oriented programming ]
 
speach
speachspeach
speach
 
DotNetNuke Client API -DragDropAdminModules.pdf
DotNetNuke Client API -DragDropAdminModules.pdfDotNetNuke Client API -DragDropAdminModules.pdf
DotNetNuke Client API -DragDropAdminModules.pdf
 
distributing computing
distributing computingdistributing computing
distributing computing
 
Learning MVC Part 3 Creating MVC Application with EntityFramework
Learning MVC Part 3 Creating MVC Application with EntityFrameworkLearning MVC Part 3 Creating MVC Application with EntityFramework
Learning MVC Part 3 Creating MVC Application with EntityFramework
 
How Android Architecture Components can Help You Improve Your App’s Design?
How Android Architecture Components can Help You Improve Your App’s Design?How Android Architecture Components can Help You Improve Your App’s Design?
How Android Architecture Components can Help You Improve Your App’s Design?
 

More from ShaiAlmog1

The Duck Teaches Learn to debug from the masters. Local to production- kill ...
The Duck Teaches  Learn to debug from the masters. Local to production- kill ...The Duck Teaches  Learn to debug from the masters. Local to production- kill ...
The Duck Teaches Learn to debug from the masters. Local to production- kill ...
ShaiAlmog1
 
create-netflix-clone-06-client-ui.pdf
create-netflix-clone-06-client-ui.pdfcreate-netflix-clone-06-client-ui.pdf
create-netflix-clone-06-client-ui.pdf
ShaiAlmog1
 
create-netflix-clone-01-introduction_transcript.pdf
create-netflix-clone-01-introduction_transcript.pdfcreate-netflix-clone-01-introduction_transcript.pdf
create-netflix-clone-01-introduction_transcript.pdf
ShaiAlmog1
 
create-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdfcreate-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdf
ShaiAlmog1
 
create-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdfcreate-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdf
ShaiAlmog1
 
create-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdfcreate-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdf
ShaiAlmog1
 
create-netflix-clone-06-client-ui_transcript.pdf
create-netflix-clone-06-client-ui_transcript.pdfcreate-netflix-clone-06-client-ui_transcript.pdf
create-netflix-clone-06-client-ui_transcript.pdf
ShaiAlmog1
 
create-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdfcreate-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdf
ShaiAlmog1
 
create-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdfcreate-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdf
ShaiAlmog1
 
create-netflix-clone-05-client-model_transcript.pdf
create-netflix-clone-05-client-model_transcript.pdfcreate-netflix-clone-05-client-model_transcript.pdf
create-netflix-clone-05-client-model_transcript.pdf
ShaiAlmog1
 
create-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdfcreate-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdf
ShaiAlmog1
 
create-netflix-clone-05-client-model.pdf
create-netflix-clone-05-client-model.pdfcreate-netflix-clone-05-client-model.pdf
create-netflix-clone-05-client-model.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part II.pdf
Creating a Whatsapp Clone - Part II.pdfCreating a Whatsapp Clone - Part II.pdf
Creating a Whatsapp Clone - Part II.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part IX - Transcript.pdf
Creating a Whatsapp Clone - Part IX - Transcript.pdfCreating a Whatsapp Clone - Part IX - Transcript.pdf
Creating a Whatsapp Clone - Part IX - Transcript.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part II - Transcript.pdf
Creating a Whatsapp Clone - Part II - Transcript.pdfCreating a Whatsapp Clone - Part II - Transcript.pdf
Creating a Whatsapp Clone - Part II - Transcript.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part V - Transcript.pdf
Creating a Whatsapp Clone - Part V - Transcript.pdfCreating a Whatsapp Clone - Part V - Transcript.pdf
Creating a Whatsapp Clone - Part V - Transcript.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part IV - Transcript.pdf
Creating a Whatsapp Clone - Part IV - Transcript.pdfCreating a Whatsapp Clone - Part IV - Transcript.pdf
Creating a Whatsapp Clone - Part IV - Transcript.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part IV.pdf
Creating a Whatsapp Clone - Part IV.pdfCreating a Whatsapp Clone - Part IV.pdf
Creating a Whatsapp Clone - Part IV.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part I - Transcript.pdf
Creating a Whatsapp Clone - Part I - Transcript.pdfCreating a Whatsapp Clone - Part I - Transcript.pdf
Creating a Whatsapp Clone - Part I - Transcript.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part IX.pdf
Creating a Whatsapp Clone - Part IX.pdfCreating a Whatsapp Clone - Part IX.pdf
Creating a Whatsapp Clone - Part IX.pdf
ShaiAlmog1
 

More from ShaiAlmog1 (20)

The Duck Teaches Learn to debug from the masters. Local to production- kill ...
The Duck Teaches  Learn to debug from the masters. Local to production- kill ...The Duck Teaches  Learn to debug from the masters. Local to production- kill ...
The Duck Teaches Learn to debug from the masters. Local to production- kill ...
 
create-netflix-clone-06-client-ui.pdf
create-netflix-clone-06-client-ui.pdfcreate-netflix-clone-06-client-ui.pdf
create-netflix-clone-06-client-ui.pdf
 
create-netflix-clone-01-introduction_transcript.pdf
create-netflix-clone-01-introduction_transcript.pdfcreate-netflix-clone-01-introduction_transcript.pdf
create-netflix-clone-01-introduction_transcript.pdf
 
create-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdfcreate-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdf
 
create-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdfcreate-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdf
 
create-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdfcreate-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdf
 
create-netflix-clone-06-client-ui_transcript.pdf
create-netflix-clone-06-client-ui_transcript.pdfcreate-netflix-clone-06-client-ui_transcript.pdf
create-netflix-clone-06-client-ui_transcript.pdf
 
create-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdfcreate-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdf
 
create-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdfcreate-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdf
 
create-netflix-clone-05-client-model_transcript.pdf
create-netflix-clone-05-client-model_transcript.pdfcreate-netflix-clone-05-client-model_transcript.pdf
create-netflix-clone-05-client-model_transcript.pdf
 
create-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdfcreate-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdf
 
create-netflix-clone-05-client-model.pdf
create-netflix-clone-05-client-model.pdfcreate-netflix-clone-05-client-model.pdf
create-netflix-clone-05-client-model.pdf
 
Creating a Whatsapp Clone - Part II.pdf
Creating a Whatsapp Clone - Part II.pdfCreating a Whatsapp Clone - Part II.pdf
Creating a Whatsapp Clone - Part II.pdf
 
Creating a Whatsapp Clone - Part IX - Transcript.pdf
Creating a Whatsapp Clone - Part IX - Transcript.pdfCreating a Whatsapp Clone - Part IX - Transcript.pdf
Creating a Whatsapp Clone - Part IX - Transcript.pdf
 
Creating a Whatsapp Clone - Part II - Transcript.pdf
Creating a Whatsapp Clone - Part II - Transcript.pdfCreating a Whatsapp Clone - Part II - Transcript.pdf
Creating a Whatsapp Clone - Part II - Transcript.pdf
 
Creating a Whatsapp Clone - Part V - Transcript.pdf
Creating a Whatsapp Clone - Part V - Transcript.pdfCreating a Whatsapp Clone - Part V - Transcript.pdf
Creating a Whatsapp Clone - Part V - Transcript.pdf
 
Creating a Whatsapp Clone - Part IV - Transcript.pdf
Creating a Whatsapp Clone - Part IV - Transcript.pdfCreating a Whatsapp Clone - Part IV - Transcript.pdf
Creating a Whatsapp Clone - Part IV - Transcript.pdf
 
Creating a Whatsapp Clone - Part IV.pdf
Creating a Whatsapp Clone - Part IV.pdfCreating a Whatsapp Clone - Part IV.pdf
Creating a Whatsapp Clone - Part IV.pdf
 
Creating a Whatsapp Clone - Part I - Transcript.pdf
Creating a Whatsapp Clone - Part I - Transcript.pdfCreating a Whatsapp Clone - Part I - Transcript.pdf
Creating a Whatsapp Clone - Part I - Transcript.pdf
 
Creating a Whatsapp Clone - Part IX.pdf
Creating a Whatsapp Clone - Part IX.pdfCreating a Whatsapp Clone - Part IX.pdf
Creating a Whatsapp Clone - Part IX.pdf
 

Recently uploaded

Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
Safe Software
 
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
Product School
 
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
Product School
 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
OnBoard
 
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMsTo Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
Paul Groth
 
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
BookNet Canada
 
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
DanBrown980551
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance
 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
91mobiles
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
Cheryl Hung
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
Guy Korland
 
Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...
Product School
 
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Jeffrey Haguewood
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
Laura Byrne
 
When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...
Elena Simperl
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
Kari Kakkonen
 
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
Sri Ambati
 
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Product School
 
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Thierry Lestable
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
DianaGray10
 

Recently uploaded (20)

Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
 
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
 
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
 
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMsTo Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
 
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
 
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
 
Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...
 
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
 
When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
 
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
 
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
 
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
 

create-netflix-clone-03-server_transcript.pdf

  • 1. Creating a Netflix Clone III In the 3rd part we’ll dive right into the model objects representing the server and ultimately the front end code. If you’re unfamiliar with entities, JPA, UUID etc. I suggest going back to the previous modules and refreshing your memory a bit as we’ll build a lot on top of that.
 One way in which this will be different though is the usage of Lombok which will make the code far more terse. Still the code here is mostly mock. The real world Netflix has a lot of code but most of it applies to algorithmic scheduling, user management, scaling etc. All of these aren’t applicable here. In this lesson our focus will be on entities and Data Transfer Objects also known as DTOs which I sometimes mixed with data access objects or DAO. There is overlap between both of those concepts but what we have is generally DTOs as they transfer data to the client. They don’t just abstract the database layer.
  • 2. codenameone.com github.com/codenameone/CodenameOne Server Internals In the 3rd part we’ll dive right into the model objects representing the server and ultimately the front end code. If you’re unfamiliar with entities, JPA, UUID etc. I suggest going back to the previous modules and refreshing your memory a bit as we’ll build a lot on top of that.
 One way in which this will be different though is the usage of Lombok which will make the code far more terse. Still the code here is mostly mock. The real world Netflix has a lot of code but most of it applies to algorithmic scheduling, user management, scaling etc. All of these aren’t applicable here. In this lesson our focus will be on entities and Data Transfer Objects also known as DTOs which I sometimes mixed with data access objects or DAO. There is overlap between both of those concepts but what we have is generally DTOs as they transfer data to the client. They don’t just abstract the database layer.
  • 3. codenameone.com github.com/codenameone/CodenameOne Server Internals Now that we know Lombok basics we can move on to the server The code is mostly mock code We’ll start with the entity model code first In the 3rd part we’ll dive right into the model objects representing the server and ultimately the front end code. If you’re unfamiliar with entities, JPA, UUID etc. I suggest going back to the previous modules and refreshing your memory a bit as we’ll build a lot on top of that.
 One way in which this will be different though is the usage of Lombok which will make the code far more terse. Still the code here is mostly mock. The real world Netflix has a lot of code but most of it applies to algorithmic scheduling, user management, scaling etc. All of these aren’t applicable here. In this lesson our focus will be on entities and Data Transfer Objects also known as DTOs which I sometimes mixed with data access objects or DAO. There is overlap between both of those concepts but what we have is generally DTOs as they transfer data to the client. They don’t just abstract the database layer.
  • 4. @Entity @Data @AllArgsConstructor @NoArgsConstructor public class Content { @Id @GeneratedValue(strategy = GenerationType.AUTO) private UUID id; private String name; private String description; @OneToOne private Media heroImage; @OneToOne private Media icon; @OneToOne private Media logo; @ManyToMany private Set<Media> videos; public ContentDTO getDTO() { Map<VideoQuality, String> qualityUrls = videos.stream(). collect(Collectors. Source Listing - Content codenameone.com github.com/codenameone/CodenameOne Writing an entity with Lombok is much easier. There are no, getters, setters, constructors, equals, hash code etc. Notice we still use JPA just like we used to so we have the JPA entity annotation and then the Lombok annotations.
  • 5. @Entity @Data @AllArgsConstructor @NoArgsConstructor public class Content { @Id @GeneratedValue(strategy = GenerationType.AUTO) private UUID id; private String name; private String description; @OneToOne private Media heroImage; @OneToOne private Media icon; @OneToOne private Media logo; @ManyToMany private Set<Media> videos; public ContentDTO getDTO() { Map<VideoQuality, String> qualityUrls = videos.stream(). collect(Collectors. Source Listing - Content codenameone.com github.com/codenameone/CodenameOne Everything works as you would expect including the primary key definition etc. Notice I chose to go with a UUID object as a primary key coupled with auto-generation. That’s a much simpler trick than the one I picked in previous modules.
  • 6. codenameone.com github.com/codenameone/CodenameOne UUID Keys Strings as keys are important, they eliminate scanning attacks JPA lets us use the UUID class and the rest is pretty much seamless This could be costly for RDBMS inserts Unless you’re doing millions of inserts this shouldn’t be a problem We already talked about using strings for keys. When we use a UUID object we get a long string that isn’t guessable in the database. That means that we can expose that primary key to the end user without worrying that he might use it to scan through details of other users as the string is pretty long and hard to guess. As we saw, we just need to use the UUID object type. There are several other strategies for generating a UUID in JPA. I chose the simplest one, it might not be the best one but it is convenient. So why doesn’t everyone use this approach? Turns out it’s much slower than using numeric auto-increment values on a database column. DB’s such as MySQL are heavily optimised for auto-increment fields and String based primary keys are just slower to insert. Some developers consider that a non-starter especially when looking at the performance graph which is “scary”. Performance really takes a dive for insert operations while it remains flat when using long auto-increment fields. Personally I don’t think that’s a problem even for a video app like this. You wouldn’t insert too often and read operations are still pretty fast. This might become an issue if you have a log or auditing table that might include multiple insert operations per second. At that point you’d need to use a long for the primary key and make sure never to expose it externally.
  • 7. @Entity @Data @AllArgsConstructor @NoArgsConstructor public class Content { @Id @GeneratedValue(strategy = GenerationType.AUTO) private UUID id; private String name; private String description; @OneToOne private Media heroImage; @OneToOne private Media icon; @OneToOne private Media logo; @ManyToMany private Set<Media> videos; public ContentDTO getDTO() { Map<VideoQuality, String> qualityUrls = videos.stream(). collect(Collectors. toMap(Media::getQuality, Media::getMediaURL)); return new ContentDTO(id.toString(), Source Listing - Content codenameone.com github.com/codenameone/CodenameOne The name and description fields correspond to these fields in the database. This is the entire definition as the accessors are generated automatically
  • 8. @Data @AllArgsConstructor @NoArgsConstructor public class Content { @Id @GeneratedValue(strategy = GenerationType.AUTO) private UUID id; private String name; private String description; @OneToOne private Media heroImage; @OneToOne private Media icon; @OneToOne private Media logo; @ManyToMany private Set<Media> videos; public ContentDTO getDTO() { Map<VideoQuality, String> qualityUrls = videos.stream(). collect(Collectors. toMap(Media::getQuality, Media::getMediaURL)); return new ContentDTO(id.toString(), name, description, getMedia(heroImage), getMedia(icon), getMedia(logo), qualityUrls); Source Listing - Content codenameone.com github.com/codenameone/CodenameOne We have three one to one media relations. These include the three images for every content item. Specifically: - The hero image which is the big picture that appears on top of the application - The show logo is displayed on top of the hero image. It’s a separate image to support different device aspect ratio and layout - The icon is the image representing a show within the list
  • 9. @Data @AllArgsConstructor @NoArgsConstructor public class Content { @Id @GeneratedValue(strategy = GenerationType.AUTO) private UUID id; private String name; private String description; @OneToOne private Media heroImage; @OneToOne private Media icon; @OneToOne private Media logo; @ManyToMany private Set<Media> videos; public ContentDTO getDTO() { Map<VideoQuality, String> qualityUrls = videos.stream(). collect(Collectors. toMap(Media::getQuality, Media::getMediaURL)); return new ContentDTO(id.toString(), name, description, getMedia(heroImage), getMedia(icon), getMedia(logo), qualityUrls); Source Listing - Content codenameone.com github.com/codenameone/CodenameOne Finally we have the actual video files which we store in media objects as well. We can have multiple video files representing different quality levels of the video. In real life we can have even more options such as different aspect ratios, languages etc. Normally I would like this to be a Map between quality and media but this is a bit challenging to represent correctly in JPA so I left this as a simple set.
  • 10. @OneToOne private Media heroImage; @OneToOne private Media icon; @OneToOne private Media logo; @ManyToMany private Set<Media> videos; public ContentDTO getDTO() { Map<VideoQuality, String> qualityUrls = videos.stream(). collect(Collectors. toMap(Media::getQuality, Media::getMediaURL)); return new ContentDTO(id.toString(), name, description, getMedia(heroImage), getMedia(icon), getMedia(logo), qualityUrls); } private byte[] getMedia(Media m) { return m == null ? null : m.getMedia(); } } Source Listing - Content codenameone.com github.com/codenameone/CodenameOne For convenience we place the DTO creation within the entity object. This code is mostly just the construction but it there’s one block where we convert the media objects
  • 11. @OneToOne private Media heroImage; @OneToOne private Media icon; @OneToOne private Media logo; @ManyToMany private Set<Media> videos; public ContentDTO getDTO() { Map<VideoQuality, String> qualityUrls = videos.stream(). collect(Collectors. toMap(Media::getQuality, Media::getMediaURL)); return new ContentDTO(id.toString(), name, description, getMedia(heroImage), getMedia(icon), getMedia(logo), qualityUrls); } private byte[] getMedia(Media m) { return m == null ? null : m.getMedia(); } } Source Listing - Content codenameone.com github.com/codenameone/CodenameOne Map<VideoQuality, String> qualityUrls = new HashMap<>(); for (Media video : videos) { qualityUrls.put(video.getQuality(), video.getMediaURL()); } In the DTO it makes more sense to hold the media as a map instead of a list or set. So we translate the video to to a map. I find the stream syntax a bit obtuse sometimes. This is how it would look with a standard for loop. Essentially for each element we replace the content with a map where the key is the quality and the value is the media URL.
  • 12. @OneToOne private Media heroImage; @OneToOne private Media icon; @OneToOne private Media logo; @ManyToMany private Set<Media> videos; public ContentDTO getDTO() { Map<VideoQuality, String> qualityUrls = videos.stream(). collect(Collectors. toMap(Media::getQuality, Media::getMediaURL)); return new ContentDTO(id.toString(), name, description, getMedia(heroImage), getMedia(icon), getMedia(logo), qualityUrls); } private byte[] getMedia(Media m) { return m == null ? null : m.getMedia(); } } Source Listing - Content codenameone.com github.com/codenameone/CodenameOne Once this is done we create a new DTO object with the automatic constructor and return it.
  • 13. @OneToOne private Media heroImage; @OneToOne private Media icon; @OneToOne private Media logo; @ManyToMany private Set<Media> videos; public ContentDTO getDTO() { Map<VideoQuality, String> qualityUrls = videos.stream(). collect(Collectors. toMap(Media::getQuality, Media::getMediaURL)); return new ContentDTO(id.toString(), name, description, getMedia(heroImage), getMedia(icon), getMedia(logo), qualityUrls); } private byte[] getMedia(Media m) { return m == null ? null : m.getMedia(); } } Source Listing - Content codenameone.com github.com/codenameone/CodenameOne And finally I also added a small helper method to make the code above a bit simpler. So we won’t get a null pointer exception if the media is null.
  • 14. @Data @AllArgsConstructor @NoArgsConstructor public class ContentDTO { private String id; private String name; private String description; private byte[] heroImage; private byte[] icon; private byte[] logo; private Map<VideoQuality, String> videoUrls; } Source Listing - ContentDTO codenameone.com github.com/codenameone/CodenameOne This is the DTO object we just created. Notice it’s super simple and mostly consists of the Lombok annotations.
  • 15. @Data @AllArgsConstructor @NoArgsConstructor public class ContentDTO { private String id; private String name; private String description; private byte[] heroImage; private byte[] icon; private byte[] logo; private Map<VideoQuality, String> videoUrls; } Source Listing - ContentDTO codenameone.com github.com/codenameone/CodenameOne The strings just map directly to the entity. There’s nothing to say here.
  • 16. @Data @AllArgsConstructor @NoArgsConstructor public class ContentDTO { private String id; private String name; private String description; private byte[] heroImage; private byte[] icon; private byte[] logo; private Map<VideoQuality, String> videoUrls; } Source Listing - ContentDTO codenameone.com github.com/codenameone/CodenameOne For the media I chose to include the icons themselves. I could have taken the approach of returning URLs for the media which might have advantages in the future. For now this is simpler but possibly not as efficient. Using a URL would have had the advantage of caching the data locally for future refreshes. Using the actual icon means all the data is transferred with one request.
  • 17. @Data @AllArgsConstructor @NoArgsConstructor public class ContentDTO { private String id; private String name; private String description; private byte[] heroImage; private byte[] icon; private byte[] logo; private Map<VideoQuality, String> videoUrls; } Source Listing - ContentDTO codenameone.com github.com/codenameone/CodenameOne This is the map we created for the media items. We already discussed this in the stream part before. It maps between the video quality enum and the string URL.
  • 18. package com.codename1.demos.netflixclone.model; public enum VideoQuality { NONE, LOW, MEDIUM, HIGH } Source Listing - VideoQuality codenameone.com github.com/codenameone/CodenameOne For the sake of completeness this is the video quality enum. Pretty simple but matches what we need right now.
  • 19. @Entity @Data @AllArgsConstructor @NoArgsConstructor public class Media { @Id @GeneratedValue(strategy = GenerationType.AUTO) private UUID id; private String name; private String mimeType; private Instant modified; private long size; @Lob @Column(name = "media", columnDefinition="BLOB") private byte[] media; private String mediaURL; private VideoQuality quality; } Source Listing - Media codenameone.com github.com/codenameone/CodenameOne The media entity is another standard Lombok entity with the standard trimmings.
  • 20. @Entity @Data @AllArgsConstructor @NoArgsConstructor public class Media { @Id @GeneratedValue(strategy = GenerationType.AUTO) private UUID id; private String name; private String mimeType; private Instant modified; private long size; @Lob @Column(name = "media", columnDefinition="BLOB") private byte[] media; private String mediaURL; private VideoQuality quality; } Source Listing - Media codenameone.com github.com/codenameone/CodenameOne We use the same UUID primary key generation logic
  • 21. @Entity @Data @AllArgsConstructor @NoArgsConstructor public class Media { @Id @GeneratedValue(strategy = GenerationType.AUTO) private UUID id; private String name; private String mimeType; private Instant modified; private long size; @Lob @Column(name = "media", columnDefinition="BLOB") private byte[] media; private String mediaURL; private VideoQuality quality; } Source Listing - Media codenameone.com github.com/codenameone/CodenameOne Rest of the stuff is pretty standard, notice that we store the modified time as an Instant instead of Date. Instant is a Java 8 date/time API class. It represents a timestamp and is more convenient to use than date.
  • 22. @Entity @Data @AllArgsConstructor @NoArgsConstructor public class Media { @Id @GeneratedValue(strategy = GenerationType.AUTO) private UUID id; private String name; private String mimeType; private Instant modified; private long size; @Lob @Column(name = "media", columnDefinition="BLOB") private byte[] media; private String mediaURL; private VideoQuality quality; } Source Listing - Media codenameone.com github.com/codenameone/CodenameOne The media data is stored in blob storage in the database
  • 23. @Entity @Data @AllArgsConstructor @NoArgsConstructor public class Media { @Id @GeneratedValue(strategy = GenerationType.AUTO) private UUID id; private String name; private String mimeType; private Instant modified; private long size; @Lob @Column(name = "media", columnDefinition="BLOB") private byte[] media; private String mediaURL; private VideoQuality quality; } Source Listing - Media codenameone.com github.com/codenameone/CodenameOne Finally the URL to the media and the video quality enum are stored as well. That means we can have multiple instances of the same media object for various quality levels. One thing I didn’t cover here is the repositories for the entity objects. They’re all empty as we don’t need any finder methods for this specific demo so it’s all pretty trivial.
  • 24. codenameone.com github.com/codenameone/CodenameOne Thank You Thanks for watching I hope you’ll enjoy the rest of the course and find it educational
  • 25. Thank You Thanks for watching I hope you’ll enjoy the rest of the course and find it educational
  • 26. Thanks for watching I hope you’ll enjoy the rest of the course and find it educational