Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JavaDependencyInjection #1001

Open
wants to merge 45 commits into
base: main
Choose a base branch
from
Open

JavaDependencyInjection #1001

wants to merge 45 commits into from

Conversation

VladSlob
Copy link

@VladSlob VladSlob commented Sep 3, 2024

No description provided.

Copy link

@mateacademy-ai-mentor mateacademy-ai-mentor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there! It looks like there's a bit more work to do before we can merge this in. 🛠️ While the main parts are looking great, we need to address a few things to align with best practices and the project's requirements. Here's what we need to fix:

  • Let's catch ReflectiveOperationException instead of multiple separate exceptions to streamline the code.
  • Consider making the implementations map a class field for better efficiency.
  • We should improve the exception messages to be more informative, helping us understand what went wrong and why.
  • Don't forget to add a @Target annotation to your custom annotations to specify where they can be applied.

Once you've made these changes, we'll be all set to approve this PR. Keep up the good work, you're almost there! 👍

✨ Please rate this review in the Platform's notification center. I will be grateful for your feedback! ✨


@Retention(RetentionPolicy.RUNTIME)
public @interface Component {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the checklist, custom annotations should have a @Target annotation to specify where this annotation can be used. For example, if @Component is meant to be used on classes, you should add @Target(ElementType.TYPE).

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the checklist, custom annotations should have a @target annotation to specify where this annotation can be used. For example, if @component is meant to be used on classes, you should add @target(ElementType.TYPE).

Comment on lines 16 to 17
if (!interfaceClazz.isInterface()) {
throw new RuntimeException("Only interfaces are supported");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The exception message could be more informative. According to the checklist, when throwing an exception, it should contain an informative message. Consider including the type of the class that is not an interface.

Comment on lines 21 to 22
if (implClass == null || !implClass.isAnnotationPresent(Component.class)) {
throw new RuntimeException("No implementation found for " + interfaceClazz.getName());

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The exception message should be more informative and include the reason why the implementation wasn't found. According to the checklist, the message should indicate the missing @Component annotation if that's the case.

Comment on lines 31 to 34
Map<Class<?>, Class<?>> implementations = Map.of(
ProductService.class, ProductServiceImpl.class,
ProductParser.class, ProductParserImpl.class,
FileReaderService.class, FileReaderServiceImpl.class

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implementations map should be a class field instead of being created in the findImplementation method. This way, it's only initialized once and can be reused, which is more efficient.

Comment on lines 57 to 58
} catch (ReflectiveOperationException e) {
throw new RuntimeException("Failed to create instance of " + implClass.getName(), e);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of catching multiple exceptions separately, it's recommended to catch their common parent, ReflectiveOperationException, to simplify the code as per the checklist.


@Retention(RetentionPolicy.RUNTIME)
public @interface Component {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the checklist, custom annotations should have a @target annotation to specify where this annotation can be used. For example, if @component is meant to be used on classes, you should add @target(ElementType.TYPE).

Comment on lines 32 to 38
if (interfaceClazz.equals(ProductService.class)) {
return ProductServiceImpl.class;
} else if (interfaceClazz.equals(ProductParser.class)) {
return ProductParserImpl.class;
} else if (interfaceClazz.equals(FileReaderService.class)) {
return FileReaderServiceImpl.class;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

create a hashmap field

@VladSlob VladSlob requested a review from okuzan September 4, 2024 10:39

@Retention(RetentionPolicy.RUNTIME)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add target

@@ -3,18 +3,12 @@
import java.math.BigDecimal;

public class Product {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

revert changes

* @return newly create {@link Product} object based on the `productInfo` input.
*/
Product parse(String productInfo);
Product parse(String line);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

revert changes

@@ -4,5 +4,7 @@
import mate.academy.model.Product;

public interface ProductService {
List<Product> getAllFromFile(String filePath);
List<Product> getAllProducts();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

revert changes

public class FileReaderServiceImpl implements FileReaderService {
@Override
public List<String> readFile(String fileName) {
try {
return Files.readAllLines(new File(fileName).toPath());
return Files.lines(new File(fileName).toPath())

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

revert changes

} catch (IOException e) {
throw new RuntimeException("Can't read file: " + fileName, e);
throw new RuntimeException("Can't read file " + fileName, e);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

revert changes

product.setDescription(data[DESCRIPTION_POSITION]);
product.setPrice(new BigDecimal(data[PRICE_POSITION]));
return product;
public Product parse(String line) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

revert changes

private FileReaderService fileReaderService;

@Override
public List<Product> getAllFromFile(String filePath) {
return fileReaderService.readFile(filePath)
public List<Product> getAllProducts() {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

revert changes

public Object getInstance(Class<?> interfaceClazz) {
return null;
public <T> T getInstance(Class<T> interfaceClazz) {
Class<?> implClass = interfaceToImplementation.get(interfaceClazz);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not full implementation os Injector

The convention is to use Component on the classes that are used for instance creation (usually these are interface implementations) and Inject to mark fields that need to be initialized. If the Component annotation is missing above the class, we shouldn't be able to create an instance of this class in Injector, and we should throw an exception

Don't forget about annotations checks in your Injector class.
Let's check instances map before new instance creation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants