Activities of "Denis"

I created several modules using ABP suite. Every module provides API, does not have Web GUI. Also I have Application which generated by ABP Suite. I included my modules to application. I run application and call endpoint of module. The endpoint returns OK result or ERR_INCOMPLETE_CHUNKED_ENCODING. But in the log I can find BusinessException expection which thrown during endpoint call. Also before this expection there is "An exception occurred, but response has already started" message. The expection is thrown in local event handler, which is triggered in by domain entity. When I run module separatly, using host in module solution, endpoint works well and returns error when exception occurs

Endpoint

 [Authorize(ProductManagementPermissions.Products.Create)]
        public virtual async Task<ProductDto> CreateProduct(ProductCreateDto input)
        {
            Product product;
            
        var attributeSet =
            await _attributeSetRepository.InsertAsync(new AttributeSet(_guidGenerator.Create()), true);
        var imageUri = !string.IsNullOrWhiteSpace(input.ImageUri) ? new Uri(input.ImageUri) : null;

        product = new Product(
            _guidGenerator.Create(),
            _currentTenant.Id,
            new ProductTitle(input.Title),
            attributeSet,
            new ProductCode(input.Code),
            imageUri);

            await _productRepository.InsertAsync(product);
            
            return ObjectMapper.Map<Product, ProductDto>(product);
        }

Product

public class Product : FullAuditedAggregateRoot<Guid>, IMultiTenant
    {
        public Guid? TenantId { get; }
        public Guid? GroupId { get; }
        public Guid AttributeSetId { get; }
        public ProductTitle Title { get; private set; }
        public ProductCode Code { get; private set; }
        public Uri? ImageUri { get; private set; }

        protected Product()
        {

        }

        public Product(
            Guid id,
            Guid? tenantId,
            ProductTitle title,
            AttributeSet attributeSet,
            ProductCode productCode,
            Uri? imageUri = null)
            : base(id)
        {
            TenantId = tenantId;
            AttributeSetId = attributeSet.Id;
            ImageUri = imageUri;
            SetCode(productCode);
            SetTitle(title);
        }

        internal Product(
            Guid id, 
            Guid? tenantId,
            Group group,
            ProductTitle title, 
            AttributeSet attributeSet, 
            ProductCode productCode, 
            Uri? imageUri = null)
            : this(id, tenantId, title, attributeSet, productCode, imageUri)
        {
            GroupId = group.Id;
        }

        public StockKeepingUnit CreateSku(Guid id, SkuCode code, SkuTitle title, AttributeSet attributeSet)
        {
            Check.NotNull(attributeSet.ParentAttributeSetId, nameof(attributeSet.ParentAttributeSetId));
            
            var childHasDifferentParentSet = AttributeSetId != attributeSet.ParentAttributeSetId;

            if (childHasDifferentParentSet)
            {
                throw new AttributeSetNotInheritedFromParentAttributeSetException(
                    parentSetId: AttributeSetId,
                    parentSetIdInChild: attributeSet.ParentAttributeSetId.Value);
            }

            return new StockKeepingUnit(
                id,
                TenantId,
                this,
                attributeSet,
                title,
                code,
                ImageUri);
        }

        public void ChangeTitle(ProductTitle title)
        {
            SetTitle(title);
        }

        public void ChangeImageUri(Uri imageUri)
        {
            Check.NotNull(imageUri, nameof(imageUri));
        }

        private void SetTitle(ProductTitle title)
        {
            Check.NotNull(title, nameof(title));
           
            Title = title;
            
            AddLocalEvent(new ProductTitleAddingEvent()
            {
                Title = title
            });
        }

        private void SetCode(ProductCode productCode)
        {
            Check.NotNull(productCode, nameof(productCode));

            Code = productCode;
            
            AddLocalEvent(new ProductCodeAddingEvent()
            {
                ProductCode = productCode
            });
        }
    }

Event handler

public class ProductEventHandler : 
            ILocalEventHandler<ProductTitleAddingEvent>,
            ILocalEventHandler<ProductCodeAddingEvent>,
            ITransientDependency
    {
        private readonly ICurrentTenant _currentTenant;
        private readonly IProductRepository _productRepository;

        public ProductEventHandler(
            ICurrentTenant currentTenant,
            IProductRepository productRepository)
        {
            _currentTenant = currentTenant;
            _productRepository = productRepository;
        }

        public async Task HandleEventAsync(ProductTitleAddingEvent eventData)
        {
            if (await TitleAlreadyExist(eventData.Title))
            {
                throw new AlreadyExistException(eventData.Title.Value, nameof(Product));
            }
        }

        public async Task HandleEventAsync(ProductCodeAddingEvent eventData)
        {
            if (await CodeAlreadyExist(eventData.ProductCode))
            {
                throw new AlreadyExistException(eventData.ProductCode.Value, nameof(Product));
            }
        }

        private async Task<bool> TitleAlreadyExist(ProductTitle title)
        {
            return await _productRepository.CountAsync(p=>
                p.TenantId == _currentTenant.Id && p.Title.Value == title.Value) > 1;
        }

        private async Task<bool> CodeAlreadyExist(ProductCode productCode)
        {
            return await _productRepository.CountAsync(p =>
                p.TenantId == _currentTenant.Id && p.Code.Value == productCode.Value) > 1;
        }
    }
  • ABP Framework version: v4.2.0
  • UI type: Angular
  • DB provider: EF Core
  • Tiered (MVC) or Identity Server Separated (Angular): no
  • Exception message and stack trace:
  • Steps to reproduce the issue:

Hi @maliming

I have several modules which were inteded to wrok as microservices. These modules communicates with each other using Http API. But now I want put all modules in one application. My question is how to configure application that modules would get injected application services instead of http proxies, which provided by modules in application assembly?

I have modules A and B implemented using ABP module template. Also I have application which created using ABP Application Temaplate I referenced modules A and B in the application accordinly layers. Module A uses API of B (references HttpApi,Client). How can I specify implemention of required by A services, which provided by assembly B?

  • ABP Framework version: v4.2.0
  • UI type: Angular
  • DB provider: EF Core
  • Tiered (MVC) or Identity Server Separated (Angular): no
  • Exception message and stack trace:

@liangshiwei Thanks

I agree with you and I would not want to reference domain of another module. I just looking for best way and figure out that my design of modules is just wrong

What is the best way to share entity implementation between multiple modules. Eg I have Attribute entity (holds name and value) with some logic implemented inside I need to use the same implementation in several modules to DRY.

I just look at source code of ABP and found that something similar is done in Framework folder.

Thanks

  • ABP Framework version: latest
  • UI type: Angular
  • DB provider: EF Core
  • Tiered (MVC) or Identity Server Seperated (Angular): yes

Yes, thanks you!

Is there any docs for API implemented by modules? Like I want see what Identity module can provide for us in terms of communication with from our module

  • ABP Framework version: last
  • UI type: Angular
  • Tiered (MVC) or Identity Server Seperated (Angular): yes

I am looking for a way of failure handling in microservices (modules deployed as apps). Eg when make several calls to different services and one of them fails we need to rollback all changes done in previous called microervices. Does ABP provide any tool for that? How that can be implemented using ABP?

I found Saga pattern, that looks the best approach. Wondering how I can apply it with ABP modules

  • ABP Framework version: last
  • Tiered (MVC) or Identity Server Seperated (Angular): yes

@liangshiwei thanks for your reply. It is I looked for

Sorry, but it does not look you answered on my questions. Maybe I understand that wrong. Can you please explain the way how to use 2 modules communicating with each other in monolith and use them again but as microservices (2 solutions using same modules: one as monolith, another one as microservices)? It is clear how modules communicate with each other in microservices - via API and events. But it is not clear how I can use same module (eg blogging module) in monolith. Should communication with built in module still be performed via API (monolith app accessing itself via network)?

Maybe you have some sample project for the monolith best practice? It will help a lot.

Showing 31 to 40 of 42 entries
Made with ❤️ on ABP v9.1.0-rc.1. Updated on January 17, 2025, 14:13