Отзывы на курс "ПРОФЕССИОНАЛЬНЫЙ Full Stack Разработчик"
PROFESSIONAL Full Stack Developer
58 3
Информация
Комментарии (66)
Команда внимательно читает ваши комментарии и оперативно на них реагирует. Вы можете спокойно оставлять запросы на обновления или задавать любые вопросы о курсе здесь.
https://github.com/amigoscode/full-stack-professional/issues/18
I'm so angry with the new bloke... he just doesn't know how to explain things.... Actually, there is a chain of events you should know.....
You may end up with the following error:
ERROR TypeError: Cannot read properties of undefined (reading 'username') angular
Basically, when you main page is load, it tries to get the object from those two lines
[(ngModel)]="authenticationRequest.username"
[(ngModel)]="authenticationRequest.password"
the thing is my authenticationRequest - wasn't initialised and I constantly get the error.
That is why he initialises the variable with the empty in LoginComponent
object authenticationRequest: AuthenticationRequest = {};
and that's why he uses optional operator in the both two fields in the AuthenticationRequest interface
username?: string;
password?: string;
Gosh, I'm not a new to programming, but if he doesn't clear things up... it's hard to trace the error.... he just does things and you should figure out how it works and take everything for granted.
The author uses the 15th version of PrimeNG whereas nowadays the 16th is available. I'm new to Angular so I cannot say exactly the difference between those versions however you don't need to use single quotes within the usual quotes. It won't work
Here is how it should be:
transitionOptions="300ms cubic-bezier(0, 0, 0.2, 1)"
https://github.com/amigoscode/full-stack-professional/issues/17
Oh my gooooood. The more I watch the less I like.... he is soooooooo impatient and unreasonable. I have just implemented the feature of fetching a user by id. Instead of using the null in the initial state in AuthContext.jsx - I used a blank object as a kind of a guest with ROLE_GUEST.
Each request I take the user's id from the localStorage, fetch the user from the database by the id and place the user into the state. Before that I retrieve user's email from JWT and compare - if they are the same - ok. If any of localStorage values have been removed from the client's side (jwt or user id) I redirect the user to the login page and delete any data in their localStorage.
What he does in the Login component is he checks if the user is null (state). The difference is he doesn't fetch the user from the database (there is no async request) and it works. In my case, by the time it checks the user it is yet GIMMICK (guest! or it would've been null if I have done the same as he did). Anyway, what we actually need to check is not the user's state, but if the user is authenticated:
const navigate = useNavigate();
useEffect(() => {
const token = localStorage.getItem("access_token");
const id = localStorage.getItem("customer_id");
if (token && id) {
navigate("dashboard")
}
}, [])
The whole story is written in his github:
https://github.com/amigoscode/full-stack-professional/issues/16
I'm so pissed off with the Mama Samba. First of all we haven't implemented a method fetching a user by email. Do we need to implement it? - No! Fetching a user by their emails isn't a good idea. When we create a database our primary key is customers ids. Meaning it would be the fastest way to fetch the user. Moreover we already have an implementation of fetching a user by the user's id.
Come on! Mama Jambo! You could've done more than that!
I am going to be a champion for opening new cases in his GitHub. :D
https://github.com/amigoscode/full-stack-professional/issues/15
that's to say: WebSecurityConfiguration.java
.requestMatchers(HttpMethod.GET, "/api/v1/customers")
.permitAll()
He signs in to his account, then is redirected to main page (dashboard), but in the end the backend part blocks the GET request and it doesn't show the user in the list.
Why do you say we don't have the ability to create a new user within the UI ? Bloody hell, we have created a page which is available by the link http://localhost:5173/container
It's the first page we have created utilising React. Take a rest from all your hard work mate, you're tired of recording.....
I will leave the code in case you have the same issue:
@ExceptionHandler(AuthenticationServiceException.class)
public ResponseEntity handleException(
AuthenticationServiceException e,
HttpServletRequest request
) {
return new ResponseEntity(
new ApiError(
request.getRequestURI(),
e.getMessage(),
HttpStatus.UNAUTHORIZED.value(),
LocalDateTime.now()
),
HttpStatus.UNAUTHORIZED
);
}
Let's say we may try to override the value of VITE_API_BASE_URL by exposing the variable with a specific value in Dockerrun.aws.json
What he is showing in the lesson is just madness.
https://github.com/amigoscode/full-stack-professional/issues/13
So if you follow my example written in lesson 113 - 116 (down below) relating to new BeanPropertyRowMapper(Customer.class),
you need to change something. Just place getGender() and convert it to String.
@Override
public void insertCustomer(Customer customer) {
var sql = "INSERT INTO customer(name, email, age, gender) VALUES (?, ?, ?, ?)";
jdbcTemplate.update(
sql,
customer.getName(),
customer.getEmail(),
customer.getAge(),
customer.getGender().toString()
);
}
@Override
public void updateCustomer(Customer customer) {
var sql = """
UPDATE customer
SET (name, email, age, gender) = (?, ?, ?, ?)
WHERE id = ?
""";
jdbcTemplate.update(
sql,
customer.getName(),
customer.getEmail(),
customer.getAge(),
customer.getGender().toString(),
customer.getId()
);
}
2. Select your username in the top-right corner and from the drop-down menu select Account Settings.
3. Select the Security tab and then New Access Token.
(Hope it helps)
https://github.com/amigoscode/full-stack-professional/issues/12
I don't know what the difference is since I use MacOS as well as Mama Samba. However, mine is 13.3.1 Ventura. It must be the only difference.
sed -i -E 's_(/:)([^"]*)_\1'${BUILD_NUMBER}'_' Dockerrun.aws.json
!!! don't forget to replate & with your data !!!
As for his port at 03:40 - I didn't understand the issue.... how his local version of Postgres might interfere with the version of Postgres on Github (containerised)?
https://github.com/amigoscode/full-stack-professional/issues/11
https://github.com/amigoscode/full-stack-professional/issues/10
Yes, he has some irritating issues with scrolling frantically window up and down now and again, shaking the cursor like crazy....
But it's just the way he explains things. Embrace his peculiarities. You may be surrounded by people at work who would make you feel even worse. All people are strange and complicated. We are all different.
Configuring Jib plugin - the issue with mvn clean package
https://github.com/amigoscode/full-stack-professional/issues/9
You re going to encounter the issue. Mind I'm working with JDK 20. There is a chance yours is a former version;
https://github.com/amigoscode/full-stack-professional/issues/8
That's really strange! We've got a block **@BeforeEach** setup.... why don't we place the piece of code into it?
```
var customer = new Customer(
FAKER.name().fullName(),
FAKER.internet().safeEmailAddress(),
new Random().nextInt(18, 99)
);
customerJDBCDataAccessServiceUnitTest.insertCustomer(customer);
```
Why does he use the email address to find the customer we've just inserted? He basically relies on a method he hasn't tested yet. It's a shame!
If the previous test is passed we mainly need to rely on it instead.
```
@Test
void selectCustomerById() {
var customer1 = customerJDBCDataAccessServiceUnitTest.selectAllCustomers()
.stream()
.findAny()
.orElseThrow();
var customer2 = customerJDBCDataAccessServiceUnitTest.selectCustomerById(customer1.getId())
.orElseThrow();
assertThat(customer1.getId()).isEqualTo(customer2.getId());
}
```
We don't care what email our inserted user has.... All we care about is if there is a user at all. We get the user and then we test our method looking the user by its ID. Here is the code:
```
@BeforeEach
void setUp() {
customerJDBCDataAccessServiceUnitTest = new CustomerJDBCDataAccessService(getJdbcTemplate());
var customer = new Customer(
FAKER.name().fullName(),
FAKER.internet().safeEmailAddress(),
new Random().nextInt(18, 99)
);
customerJDBCDataAccessServiceUnitTest.insertCustomer(customer);
}
@Test
void selectAllCustomers() {
var customers = customerJDBCDataAccessServiceUnitTest.selectAllCustomers();
assertThat(customers).isNotEmpty();
}
@Test
void selectCustomerById() {
var customer1 = customerJDBCDataAccessServiceUnitTest.selectAllCustomers()
.stream()
.findAny()
.orElseThrow();
var customer2 = customerJDBCDataAccessServiceUnitTest.selectCustomerById(customer1.getId())
.orElseThrow();
assertThat(customer1.getId()).isEqualTo(customer2.getId());
}
```
export FORMAT="ID\t{{.ID}}\nNAME\t{{.Names}}\nIMAGE\t{{.Image}}\nPORTS\t{{.Ports}}\nCOMMAND\t{{.Command}}\nCREATED\t{{.CreatedAt}}\nSTATUS\t{{.Status}}\n"
docker ps --format=$FORMAT
BTW Before the129th lesson, don't use
assertThat(postgreSQLContainer.isHealthy()).isTrue();
it won't work with "postgres:latest". There should be a specific release supporting the feature.
updateCustomer has more unnecessary logic!
Okay folks, I just share with you my implementation. What he does is just overkill.
@Override
public void updateCustomer(Customer customer) {
var sql = """
UPDATE customer
SET (name, email, age) = (?, ?, ?)
WHERE id = ?
""";
jdbcTemplate.update(
sql,
customer.getName(),
customer.getEmail(),
customer.getAge(),
customer.getId()
);
}
@Override
public Optional selectCustomerById(Integer customerId) {
var sql = "SELECT * FROM customer c WHERE c.id = ?";
return jdbcTemplate.query(
sql,
new BeanPropertyRowMapper(Customer.class),
customerId
).stream().findAny();
}
My implementation is succinct:
@Override
public List selectAllCustomers() {
var sql = "SELECT * FROM customer";
return jdbcTemplate.query(sql, new BeanPropertyRowMapper(Customer.class));
}
and don't forget to inject the Postgres language into query. I don't know why he hasn't shown it yet.
Wow! The updateCustomer method is shown at 2:10 with a quite ridiculous implementation. Why do we need to overload the method with the logic? What's the point in all those conditions? If he had a choice between PUT and PATCH - yes, this logic would be justified, but for the PUT itself - it doesn't matter if there is a change in any object's field or it updates partially, let's say just the email or name.
The code looks disgusting and verbose.
PUT is a method of modifying resource where the client sends data that updates the entire resource .
PATCH is a method of modifying resources where the client sends partial data that is to be updated without modifying the entire data.
````
@PutMapping(
path = "{customerId}",
consumes = {
MediaType.APPLICATION_JSON_VALUE,
MediaType.APPLICATION_XML_VALUE
}
)
public void updateCustomerById(
@PathVariable("customerId") Integer customerId,
@RequestBody CustomerDto customerDto
) {
customerService.updateCustomerById(customerId, customerDto);
}
````
In the controller we use @PutMapping. PUT would update the entire resource regardless you change one field or all of them. Why bother putting any additional logic?
````
public void updateCustomerById(Integer customerId, CustomerDto customerDto) {
var customer = getCustomer(customerId);
customer.setName(customerDto.name());
customer.setEmail(customerDto.email());
customer.setAge(customerDto.age());
customerDao.updateCustomer(customer);
}
````
DONE!
public void updateCustomer(Customer customer) {
customers.add(customer)
}
And how is the method going to override the actual object in the List if it simply adds a new object to the end of the List? That's really interesting.