SlideShare a Scribd company logo
1 of 26
Download to read offline
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

Advanced Web Development
Advanced Web DevelopmentAdvanced Web Development
Advanced Web DevelopmentRobert J. Stein
 
Dao pattern
Dao patternDao pattern
Dao patternciriako
 
Nt1310 Unit 3 Language Analysis
Nt1310 Unit 3 Language AnalysisNt1310 Unit 3 Language Analysis
Nt1310 Unit 3 Language AnalysisNicole Gomez
 
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 2021David Gómez García
 
Googleappengineintro 110410190620-phpapp01
Googleappengineintro 110410190620-phpapp01Googleappengineintro 110410190620-phpapp01
Googleappengineintro 110410190620-phpapp01Tony Frame
 
DevSecCon SG 2018 Fabian Presentation Slides
DevSecCon SG 2018 Fabian Presentation SlidesDevSecCon SG 2018 Fabian Presentation Slides
DevSecCon SG 2018 Fabian Presentation SlidesFab 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 PolymerFITC
 
iOS Course day 2
iOS Course day 2iOS Course day 2
iOS Course day 2Rich 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 computingnibiganesh
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
create-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdfcreate-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
create-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdfcreate-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
create-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdfcreate-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 

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

SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Wonjun Hwang
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Bluetooth Controlled Car with Arduino.pdf
Bluetooth Controlled Car with Arduino.pdfBluetooth Controlled Car with Arduino.pdf
Bluetooth Controlled Car with Arduino.pdfngoud9212
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Neo4j
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraDeakin University
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksSoftradix Technologies
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 

Recently uploaded (20)

SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Bluetooth Controlled Car with Arduino.pdf
Bluetooth Controlled Car with Arduino.pdfBluetooth Controlled Car with Arduino.pdf
Bluetooth Controlled Car with Arduino.pdf
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning era
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping Elbows
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other Frameworks
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 

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